我有一个图形用户界面,使用JavaFX与FXML制成。
该GUI有很多组件,而不是所有的人都在一个时刻需要。
例如,假设从服务器接收部分城市的列表的GUI。 每个城市自己的标签上描述的(并且有很多节点的描述)。 该组城市中含有30个元素。
当GUI启动时,它要求城市列表服务器。 服务器返回城市的一个随机的“子集”(所以,也可以是莫斯科里加+ +纽约或圣彼得堡+东京,或者只阿姆斯特丹,或在一组的所有30个城市)。
所以。 我有没有必要让所有30个选项卡在我的节点树(我想他们会只是“吃”内存,仅此而已)。
我要管理我在我的GUI每一刻标签的数量。
第一个简单的解决办法我有如下:
- 创建一个包含所有城市部件的FXML文件
- 在控制器类的初始化,删除选项卡,这是没有必要的。
有对我有这个解决方案的问题。 首先,我不知道是否tabPane.getTabs().remove(index)
确实删除选项卡,并从节点树中的所有内容。 其次,所有不需要的标签将被initializated他们将被删除之前,所以他们会使用内存和资源,无论如何,我的GUI可以是一个比它慢不得。
第二种解决方案我已经是:
- 让很多FXMLs的。 一为所有城市,每个城市和一个城市的每个组合。
但会有办法很多FXMLs,因此该方案也没有用处。
我梦想的解决方案:
- 创建每个城市和一个与标签的主要应用程序的FXML文件。
- 在需要的时候加载FXML城市文件内容到一个标签动态。
因此,如果有人对这个任务的任何想法,或者知道该解决方案,请大家帮我吧?
好吧,如果我理解正确的你,这里是我的建议维多利亚;
假设主要的应用程序FXML包含TabPane
某处吧:
// other controls
<TabPane fx:id="tabPane" id="tabPane">
<tabs>
</tabs>
</TabPane>
// other controls
在主控制器:
// TabPane in fxml
@FXML
private TabPane tabPane;
// The FXMLLoader
private FXMLLoader fXMLLoader = new FXMLLoader();
// City list fetched from server
private String[] cityList = {"Moscow", "Stambul", "New York", "Bishkek"};
// OPTIONAL : Map for "city name - city fxml controller" pairs
private Map<String, Object> cityControllerMap = new HashMap<String, Object>();
// Belows are in init method
// Add only tabs dynamically but not their content
for (String city : cityList) {
tabPane.getTabs().add(new Tab(city));
}
// It is important to call it before adding ChangeListener to the tabPane to avoid NPE and
// to be able fire the manual selection event below. Otherwise the 1st tab will be selected
// with empty content.
tabPane.getSelectionModel().clearSelection();
// Add Tab ChangeListener
tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
@Override
public void changed(ObservableValue<? extends Tab> observable, Tab oldValue, Tab newValue) {
System.out.println("Tab selected: " + newValue.getText());
if (newValue.getContent() == null) {
try {
// Loading content on demand
Parent root = (Parent) fXMLLoader.load(this.getClass().getResource(newValue.getText() + ".fxml").openStream());
newValue.setContent(root);
// OPTIONAL : Store the controller if needed
cityControllerMap.put(newValue.getText(), fXMLLoader.getController());
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
// Content is already loaded. Update it if necessary.
Parent root = (Parent) newValue.getContent();
// Optionally get the controller from Map and manipulate the content
// via its controller.
}
}
});
// By default, select 1st tab and load its content.
tabPane.getSelectionModel().selectFirst();
如果您决定存储控制器,你可以定义一个控制器,每个城市FXML或只定义一个控制器类为所有这些并设定它像fXMLLoader.setController(new CommonCityController());
之前加载城市FXML文件。
HTH。