我有一个使用JavaFX和FXML制作的GUI。
这个GUI有很多组件,并不是所有组件都需要在一个时刻。
例如,想象一下从服务器部分接收城市列表的GUI。 每个城市都在其自己的选项卡上进行描述(并使用大量节点进行描述)。这组城市包含30个元素。
启动GUI时,它会向服务器请求城市列表。 服务器返回一个随机的“子集”城市(因此,它可以是莫斯科+里加+纽约或圣彼得堡+东京,或只有阿姆斯特丹,或一组中的所有30个城市)。
因此。我没有必要在我的节点树中拥有所有30个选项卡(我想它们只会“吃掉”内存而已。)
我想管理GUI上每时每刻的标签数量。
我的第一个简单解决方案如下:
我对此解决方案存在问题。首先,我不知道tabPane.getTabs().remove(index)
是否真的从节点树中删除了选项卡及其所有内容。其次,所有不需要的选项卡将在删除之前初始化,因此无论如何它们都将使用内存和资源,而且我的GUI可能比它更慢。
我的第二个解决方案是:
但是会有很多FXML,所以这个解决方案也没用。
我梦寐以求的解决方案:
所以,如果有人对此任务有任何想法,或者知道解决方案,请帮助我...
答案 0 :(得分:10)
好的,如果我理解正确的话,这是我的建议维多利亚;
假设主应用程序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定义一个控制器,或者为所有城市定义一个控制器类,并在加载city fxml文件之前将其设置为fXMLLoader.setController(new CommonCityController());
。
HTH。