[英]JavaFx actions between controllers
我如何做按钮动作来编辑TableView
。 当我触摸按钮时,我需要将文本从TextArea
放到表格中。 如果将System.out.println
放在inputToTable()
则可以正常工作。
public class InputController {
public TextArea inputArea;
public Button inputButton;
private TableController tableController;
public void initialize() {
tableControllerInit();
}
public void inputToTable() {
if(inputArea.getText() != "") {
tableController.tableInfo.setItems(FXCollections.observableArrayList(new InputObject(inputArea.getText())));
}
}
private void tableControllerInit() {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("table.fxml"));
fxmlLoader.load();
tableController = fxmlLoader.getController();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class TableController {
@FXML TableView<InputObject> tableInfo;
@FXML TableColumn<InputObject, String> col1;
public void initialize() {
col1.setCellValueFactory(new PropertyValueFactory<>("text"));
}
}
public class Controller implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}
public class InputObject {
String text;
public InputObject(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
<BorderPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<left>
<fx:include source="table.fxml"/>
</left>
<center>
<fx:include source="input.fxml"/>
</center>
</BorderPane>
<TableView fx:controller="sample.TableController" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:id="tableInfo" prefHeight="400.0" prefWidth="330.0">
<columns>
<TableColumn fx:id="col1" prefWidth="75.0" text="Output" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
<VBox fx:controller="sample.InputController" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" alignment="TOP_CENTER" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
<children>
<TextArea fx:id="inputArea" prefHeight="188.0" prefWidth="270.0" />
<Button fx:id="inputButton" onAction="#inputToTable" mnemonicParsing="false" text="Input">
<VBox.margin>
<Insets bottom="30.0" left="30.0" right="30.0" top="30.0" />
</VBox.margin>
</Button>
</children>
</VBox>
您加载table.fxml
两次:通过一次fx:include
主FXML文件,而一旦在InputController
,通过FXMLLoader
您在创建tableControllerInit()
方法。 因此,的两个实例TableController
被创建,一个具有从加载第一UI相关联table.fxml
,和一个与您从加载第二UI相关联table.fxml
。
通过fx:include
加载的UI将显示在主FXML文件中定义的VBox
中。 用FXMLLoader
加载的UI永远不会显示(实际上,您甚至从不保留对它的引用,只需调用loader.load()
并丢弃结果)。 当您尝试更新表的项目(顺便说一句,您真的要替换所有现有项目吗?)时,您引用的第二个控制器实例与从未显示过的UI关联。 因此,您正在更新未显示的表,并且永远不会看到任何结果。
您真正需要做的是在与两个fx:include
关联的两个控制器之间共享相同的数据。 您可以简单地通过将这两个控制器注入到主控制器中来执行此操作,如文档中的“嵌套控制器”部分所述。
首先,给fx:include
元素fx:id
属性:
<BorderPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<left>
<fx:include fx:id="table" source="table.fxml"/>
</left>
<center>
<fx:include fx:id="input" source="input.fxml"/>
</center>
</BorderPane>
然后,您可以通过创建在fx:id
后面附加单词"Controller"
字段,将控制器注入到主控制器中。 创建一个可观察的列表,它将表示表中显示的项目列表,并将其传递给每个控制器:
public class Controller implements Initializable {
@FXML
private TableController tableController ;
@FXML
private InputController inputController ;
@Override
public void initialize(URL location, ResourceBundle resources) {
ObservableList<InputObject> items = FXCollections.observableArrayList();
tableController.setTableItems(items);
inputController.setTableItems(items);
}
}
最后,只需在其他两个控制器中的每个中定义明显的方法:
public class TableController {
@FXML
private TableView<InputObject> tableInfo;
@FXML
private TableColumn<InputObject, String> col1;
public void initialize() {
col1.setCellValueFactory(new PropertyValueFactory<>("text"));
}
public void setTableItems(ObservableList<InputObject> tableItems) {
tableInfo.setItems(tableItems);
}
}
现在,该表显示了在主控制器的initalize()
方法中创建的items
列表的内容,而InputController
引用了该列表。 因此,您所需要做的就是更新InputController
中的列表。 我假设您只想向表中添加项目(而不是全部替换):
public class InputController {
@FXML
private TextArea inputArea;
@FXML
private Button inputButton;
private ObservableList<InputObject> tableItems ;
public void setTableItems(ObservableList<InputObject> tableItems) {
this.tableItems = tableItems ;
}
public void inputToTable() {
if(! inputArea.getText().isEmpty()) {
tableItems.add(new InputObject(inputArea.getText()));
}
}
}
更一般而言,如果您有更多的数据要在不同的控制器之间共享,则可以创建一个或多个“模型”类,并与控制器共享模型实例。 然后,您可以观察模型的属性并进行更新。 有关更全面的示例,请参见将MVC与JavaFx一起使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.