2017-02-22 48 views
0

我在个人项目中首次使用JavaFX进行游戏。从外部FXML控制器获取对Tab的引用

我希望能够更新Tab中的内容(添加PieChart),但是从FXML控制器外部,任何人都可以告诉我这是否可能?我如何获得对相关选项卡的引用,并且是否有方法指定我添加的项目的位置?

UPDATE:增加了一些示例代码。

希望这给的什么,我试图做一个清晰的思路:

接口:

interface ChartStrategy { 

    public void DisplayChart(Info info) 
} 

两个实现:

public class BarChartStrategy extends ChartStrategy { 

    public void DisplayChart(Info info) 
    { 
     // Create bar charts on specific tabs in the UI 
    } 
} 


public class PieChartStrategy extends ChartStrategy { 

    public void DisplayChart(Info info) 
    { 
     // Create pie charts on specific tabs in the UI 
    } 
} 

上下文:

public class ChartContext { 
    private ChartStrategy strategy; 

    public void setChartStrategy(ChartStrategy strategy) { 
    this.strategy = strategy; 
    } 

    public void drawGraphs(Info info) { 
    strategy.DisplayChart(info); 
    } 
} 

在我的控制ler,我在用户选择的文件中读取数据以生成图表,解析,例如。

@FXML 
private void handleButtonAction(ActionEvent event) { 

    // Load the file and parse the data 
    ... 

    ChartContext charts = new ChartContext(); 
    charts.setChartStrategy(new PieChartStrategy()); 
} 

所以我最初的想法是,我可以借鉴在实施中DisplayChart功能的图表,但似乎不是一个好主意 - 任何人都可以给我一些建议在这里得到这个的最佳方式工作?

+2

请问为什么?这正是控制器应该做的事情。你可以在控制器中定义一个返回特定选项卡的方法,并从你需要的地方调用它,但我不建议在控制器之外暴露UI组件。 –

+0

我正尝试使用策略模式来处理在UI中显示不同的图表类型,方法是直接从策略实施中在UI中创建图表。馊主意?参加一个关于设计模式的课程,并试图让我的头脑围绕这一点。 –

+0

不是一个坏主意,不,但是您不需要公开控制器中的UI组件就可以做到这一点。在控制器级别定义策略:即您的控制器具有对类型为策略(接口)的字段的引用。在代码中创建控制器(而不是在FXML中),指定传递给控制器​​构造函数的策略实现。然后您的控制器可以调用策略并将图表放在适当的选项卡中。 –

回答

1

我会重构这一点。

首先,让策略显示图表有点不灵活。您正在赋予策略两个职责:首先决定如何以可视方式表示数据(选择图表),然后将其实际显示在某处。这违反了单一责任原则。

所以我会做

interface ChartStrategy { 

    public Chart generateChart(Info info) 
} 

,同样的实现,当然。那么策略的责任就是提供一个图表:上下文可以决定如何处理它。

(您也可以考虑是否回到这里Chart太死板:也许你只是希望它返回一个Parent,或Node然后你的“图表”可能是,例如,一个TableView,例如。)

在战略模式的理论描述中,至少在我的解释中,“背景”只是表示“正在使用战略的东西”。所以你的上下文可能是一个视图或控制器(取决于你选择的MVC变种......)。作为一个简单的例子,你可能有类似

public class ChartTab { 

    private ChartStrategy chartGenerator ; 

    public void setChartGenerator(ChartStrategy chartGenerator) { 
     this.chartGenerator = chartGenerator ; 
    } 

    public Tab createChartTab(Info info) { 
     Tab tab = new Tab(); 
     tab.setContent(chartGenerator.generateChart(info)); 
     return tab ; 
    } 
} 

,然后在你的控制器

@FXML 
private TabPane tabPane ; 

@FXML 
private void handleButtonAction(ActionEvent event) { 

    // Load the file and parse the data 
    ... 

    ChartTab chartTab = new ChartTab(); 
    chartTab.setChartGenerator(new PieChartStrategy()); 
    tabPane.getTabs().add(chartTab.getTab(info));  
} 

也有可能只是考虑控制器的情况下(如果固定控制器,你只是创造一种

public class MyController { 

    private ChartStrategy chartGenerator ; 

    @FXML 
    private TabPane tabPane ; 

    public MyController(ChartStrategy chartGenerator) { 
     this.chartGenerator = chartGenerator ; 
    } 

    @FXML 
    private void handleButtonAction(ActionEvent event) { 

     // Load the file and parse the data 
     ... 

     Tab tab = new Tab(); 
     tab.setContent(chartGenerator.generateChart(info)); 
     tabPane.getTabs().add(tab);  
    } 

} 

注意这个控制器没有一个无参数的构造函数,所以哟:图表,这取决于你如何分割的FXML文件及其相应的控制器)的你不能在FXML文件中使用fx:controller属性(即从FXML文件中删除该属性)。相反,你会做

FXMLLoader loader = new FXMLLoader("/path/to/DataDisplay.fxml"); 
MyController controller = new MyController(new PieChartStrategy()); 
loader.setController(controller); 
Parent root = loader.load(); 

现在你有一个FXML和控制器的功能,生成图表,并在标签窗格中显示它们(或其他),但会产生什么样的图表的细节因素进入可插拔策略。你仍然有适当的MVC(或者MVP等等)封装,其中UI的细节对于视图控制器(在这里它是一个真正的主持人,但是谁在数......)是私有的。换句话说,战略对其余的观点一无所知,这是应该的。

+0

谢谢@James_D,这让我有很多想法。 –

相关问题