我有一个我正在研究的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;方式,还是有更好的选择?
答案 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<0}" />
</left>
</BorderPane>
请注意,table.selectionModel.selectedIndex+0<0
部分是一种使用的解决方法,因为JavaFX目前还没有使用null
- 安全的平等检查(table.selectionModel.selectedItem==null
不起作用)而且不能得到0
常量的类型进行比较(table.selectionModel.selectedIndex<0
),所以这似乎不是一个好的选择。