在FXML

时间:2016-11-02 04:37:36

标签: java javafx tableview fxml

我有一个我正在研究的Java项目,它使用JavaFX生成UI。我并不是一个Java程序员(一般来说不是一个程序员 - 我是CS学生),所以它有点学习经验,但一般我都在回答我的问题。我一直有自己的问题。我现在正在使用TableView找到一个粘性点,并且有点迷失 - 具体来说,我似乎无法设置任何类型的操作以响应与TableView的交互。

我项目的当前布局是Main.java,Controller.java和UI.fxml。在Main中,窗格/场景在程序启动时从UI.fxml加载。 (从技术上讲,该项目包含其他一些代码,但我试图仅发布相关的内容。)我在UI.fxml中定义了一个TableView,如下所示:

<TableView fx:id="queueTable">
    <columns>
        <TableColumn text="Title">
             <cellValueFactory>
                <PropertyValueFactory property="tableTitle"/>
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Artist">
            <cellValueFactory>
                <PropertyValueFactory property="tableArtist"/>
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Album">
        <cellValueFactory>
                <PropertyValueFactory property="tableAlbum"/>
            </cellValueFactory>
        </TableColumn>
    </columns>
</TableView>

同样,我在UI.fxml中使用onAction定义了几个按钮,如下所示:

<Button fx:id="buttonQueueAdd" text="Add" onAction="#addMediaToQueue"/>

在我以前的代码中,我能够在生成TableView的方法中定义一个事件,以便选择TableView中的项目。但是,现在,所有UI创建都是通过FXML文件完成的。 FXML文件有一个它引用的控制器类(Controller.java),其中所有操作都是为各种按钮定义的,但我似乎无法接受任何属性,如onAction,{ TableView的FXML文件中的{1}}等,它接受了一个&#39; onAction&#39; Button的属性。

似乎我可以通过在我的Main类中定义动作(或者在我的Controller类中创建一个在Main类中调用的方法,在创建场景时)来获得解决方法,但是除非我在我的Controller类中使setOnMousePressed静态...然后打破了操作TableView中的项的所有函数 - 例如,我不能再向TableView / UI中添加项目,否则不会工作不刷新以显示添加的项目。

似乎最好的解决方案是不要在FXML中创建TableView,而是在FXML文件之外设置创建的TableView及其所有onMousePressed事件等,并将它们添加到我的Main中的场景中class queueTable方法。这就是以前的做法,然后它可以接受。然而,这似乎很混乱,导致我的UI元素散布在多个类和/或FXML文件中 - 这是我正在与其他几个学生一起工作的项目,我试图保留所有内容尽可能简化/组织。我是否必须咬紧牙关并且做到这一点&#34;凌乱&#34;方式,还是有更好的选择?

1 个答案:

答案 0 :(得分:0)

您仍然可以使用fxml生成TableView,但是向控制器添加initialize方法。完成对象结构后,FXMLLoader调用此方法,可用于修改fxml无法完成的对象结构:

@FXML
private void initialize() {
    queueTable.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> {
        ...
    });
}

如果您需要从Main添加此侦听器,您可以向控制器添加一个方法,并从用于创建fxml的FXMLLoader实例中获取控制器。

<强>控制器

public void addSelectedIndexListener(ChangeListener<? super Number> listener) {
    queueTable.getSelectionModel().selectedIndexProperty().addListener(listener);
}

主要

FXMLLoader loader = new FXMLLoader(fxmlUrl);
myNode = loader.load();
Controller controller = loader.getController();
controller.addSelectedIndexListener((observable, oldValue, newValue) -> {
    ...
});

请注意,属性属性应取决于选择模型的属性,您可以使用expression binding来实现所需的效果。

<BorderPane xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
    <center>
        <TableView fx:id="table" BorderPane.alignment="CENTER">
            <columns>
                <TableColumn text="value">
                    <cellValueFactory>
                        <PropertyValueFactory property="value"/>
                    </cellValueFactory>
                </TableColumn>
            </columns>
            <items>
                <FXCollections fx:factory="observableArrayList">
                    <Item value="Hello World"/>
                    <Item value="42"/>
                </FXCollections>
            </items>
        </TableView>
    </center>
    <left>
        <Button mnemonicParsing="false" text="Remove" BorderPane.alignment="CENTER" disable="${table.selectionModel.selectedIndex+0&lt;0}" />
    </left>
</BorderPane>

请注意,table.selectionModel.selectedIndex+0<0部分是一种使用的解决方法,因为JavaFX目前还没有使用null - 安全的平等检查(table.selectionModel.selectedItem==null不起作用)而且不能得到0常量的类型进行比较(table.selectionModel.selectedIndex<0),所以这似乎不是一个好的选择。