如何动态地将内容加载到JavaFX选项卡? [英] How to load content to JavaFX tabs dynamically?

查看:75
本文介绍了如何动态地将内容加载到JavaFX选项卡?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用JavaFX和FXML制作的GUI.

I have a GUI, made using JavaFX with FXML.

此GUI有很多组件,并非一次需要所有组件.

This GUI has a lot of components and not all of them are needed at one moment of time.

例如,假设有一个GUI从其服务器部分接收城市列表. 每个城市在其自己的选项卡上进行描述(并带有许多节点).城市集包含30个元素.

For example, imagine a GUI that receives from its server part a list of cities. Each city is described on its own tab (and described with a lot of nodes). The set of cities contains 30 elements.

启动GUI时,它会询问服务器以获取城市列表. 服务器返回一个随机的城市子集"(因此,它可以是莫斯科+里加+纽约或圣彼得堡+东京,或者只有阿姆斯特丹,或一组中的所有30个城市).

When the GUI is launched, it asks the server for a list of the cities. The server returns a random "sub-set" of cities (so, it can be Moscow + Riga + New York or St.Petersburg + Tokyo, or only Amsterdam, or all 30 cities in one set).

所以.我不需要在节点树中拥有所有30个选项卡(我想它们只会吃掉"内存,仅此而已).

So. I have no need to have all 30 tabs in my node tree (I suppose they'll just "eat" memory and nothing more).

我想管理每时每刻在GUI上可用的选项卡的数量.

I want to manage the amount of tabs I have at each moment on my GUI.

我拥有的第一个简单解决方案是:

The first simple solution I have is the following:

  1. 创建一个包含所有城市组件的FXML文件
  2. 在控制器类的初始化期间,删除不需要的选项卡.

此解决方案存在一些问题.首先,我不知道tabPane.getTabs().remove(index)是否真的从节点树中删除了选项卡及其所有内容.其次,所有不需要的选项卡都将被初始化,然后再将其删除,因此无论如何它们都将使用内存和资源,而且我的GUI可能比需要的要慢.

There are to problems I have with this solution. First, I don't know whether tabPane.getTabs().remove(index) really removes the tab and all its content from the nodes tree. Second, all unneeded tabs will be initializated before they will be removed, so they'll use memory and resources anyway, and my GUI can be a slower than it has to be.

我的第二个解决方案是:

The second solution I have is:

  1. 制作许多FXML.每个城市一个,每个城市一个,每个城市组合一个.

但是会有很多FXML的方法,因此该解决方案也没有用.

But there will be way to many FXMLs, so this solution is also not useful.

我梦for以求的解决方案:

The solution I dream for:

  1. 为每个城市创建一个FXML文件,并为带有标签的主应用程序创建一个FXML文件.
  2. 在需要时动态地将FXML城市文件内容加载到选项卡中.

因此,如果有人对此任务有任何想法或知道解决方案,请帮助我解决问题...

So, if someone has any ideas on this task, or knows the solution, please help my with it...

推荐答案

好吧,如果我对您的理解正确,这是我对维多利亚的建议;
假设主应用程序FXML在其中的某个位置包含TabPane:

Ok, if I understood you correctly, here is my suggestion Victoria;
Suppose the main app FXML contains TabPane somewhere in it:

// 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());进行设置.

If you decide to store the controllers, you may define a controller for every city fxml or define only one controller class for all of them and set it by like fXMLLoader.setController(new CommonCityController()); before loading city fxml file.

HTH.

这篇关于如何动态地将内容加载到JavaFX选项卡?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆