【问题标题】:Javax: ListView: load controllers by selecting item in ListViewJavax:ListView:通过在 ListView 中选择项目来加载控制器
【发布时间】:2017-12-24 14:37:48
【问题描述】:

我有视图并且有一个ListView 和一个Pane。我想将控制器添加为ListView 的项目,当我单击listView 的元素之一时,将Pane 的内容设置为其控制器内容,

例如,我有FruitsController 和VegetablesController,当然还有每个控制器对应的.fxml,当我点击第一个元素时,将Panes 元素设置为水果的tableView,否则为tableview蔬菜。我试过 <fx:include source=Fruits.fxml> 等等,但我不知道如何切换内容,以及如何在 ListView 中显示自定义名称作为元素名称。那么你有什么想法吗?

编辑:

我在这里How can I Populate a ListView in JavaFX using Custom Objects? 和JavaFX - ListView Item with an Image Button 找到了部分解决方案 但是问题仍然存在,我不知道如何以及在何处放置<fx:include> 标签,以便在我单击某个项目时加载它。

【问题讨论】:

  • 最好不要使用<fx:include>。只需在列表视图的选择模型中注册一个侦听器,并在选择更改时在控制器中加载新的 FXML。
  • 是的,这是我的解决方案,但我有 9-10 项,并且列表正在增长,所以我认为有一种更简单的方法可以不为每次我向列表中添加新项目时。为什么说“最好不要这样做”?这是一个坏方法还是不可能?
  • 不确定我是否理解。您只需要一个侦听器进行选择,然后根据选择的内容选择 FXML 文件。然后为该 FXML 文件创建一个加载器并加载它。 (我想我不明白您所说的“编写”加载程序是什么意思。)如果您使用<fx:include>,您基本上必须加载所有可能的 FXML 文件并以某种方式隐藏您不想显示的文件,这会更复杂,并且会一直将所有这些 UI 保存在内存中。也许如果您不能以简单的方式使用监听器,请发布一些代码来展示您如何尝试这样做。
  • 嗯...你是对的,将所有 UI 保存在内存中是个坏主意。在我的列表视图中添加监听器不是问题。问题是我必须在这个控制器中保留所有.fxml 路径,然后询问 lisview 的选定项:你是xController吗?...你是yController吗? 如果其中一个匹配,则加载它。但如果不是很清楚,请在几分钟内发布代码。
  • 只需为处理该问题的列表视图定义一个自定义类型。

标签: java listview javafx javafx-8


【解决方案1】:

您可以在列表视图的选择模型中注册一个监听器,并在选择更改时加载相应的视图。

例如,假设你有

public class View {

    private final String name ;
    private final Class<?> controllerType ;

    // You could assume that the resource is name+".fxml" if you want to rely on conventions like that
    // That would eliminate the need for another field here, but would prevent
    // e.g. names with whitespace etc.
    private final String resource ;

    public View(String name, Class<?> controllerType, String resource) {
        this.name = name ;
        this.controllerType = controllerType ;
        this.resource = resource ;
    }

    public String getName() {
        return name ;
    }

    public Class<?> getControllerType() {
        return controllerType ;
    }

    public String getResource() {
        return resource ;
    }

    @Override
    public String toString() {
        return name ;
    }
}

然后在 FXML 中:

<!-- imports, namespaces omitted -->

<BorderPane fx:id="root" fx:controller="app.MainController" ... >
    <left>
        <ListView fx:id="selector"/>
    </left>
</BorderPane>

在控制器中:

package app ;

public class MainController {

    @FXML
    private BorderPane root ;

    @FXML
    private ListView<View> selector ;

    public void initialize() {
        selector.getSelectionModel().selectedItemProperty().addListener((obs, oldView, newView) -> {
            if (newView == null) {
                root.setCenter(null);
            } else {
                // assumes each FXML is in the same package as its controller
                // (which I think is a nice way to organize things)
                FXMLLoader loader = new FXMLLoader(newView.getControllerType().getResource(newView.getResource()));
                try {
                    root.setCenter(loader.load());
                } catch (IOException exc) {
                    // unrecoverable...
                    throw new UncheckedIOException(exc);
                }
            }
        });

        selector.getItems().addAll(
            new View("Fruits", FruitsController.class, "Fruits.fxml"),
            new View("Vegetables", VegetablesController.class, "Vegetables.fxml")
        );
    }
}

如果所有控制器都有共同的功能,您可以让它们实现一个共同的接口(例如ProductsController),并在加载新的FXML后使用ProductsController currentController = loader.getController();从加载器中检索当前控制器。 (在这种情况下,您也可以将View 中的controllerType 的类型更改为Class&lt;? extends ProductsController&gt;。)

【讨论】:

  • 是的,正如您所写,我有一个由所有控制器实现的接口,所以我认为这是我将使用的解决方案,它更简单易懂。
  • @Sunflame 如果您愿意,可以将View 设为枚举,当然,您仍然可以做同样的事情。
  • 我会更好地使用类,但我认为我必须使用资源,因为我的 names 被翻译成多种语言并且单词之间也有空格,所以如果我理解正确,我不能使用您在 resource, 上方的评论中写的那种方式
  • `root.setCenter(loader.load());` 对我来说它说我必须用 try catch 包围,即使我放在那里 throws IOException 你知道为什么吗?为你编译代码片段?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
  • 2017-12-31
相关资源
最近更新 更多