简体   繁体   English

控制器之间的JavaFx操作

[英]JavaFx actions between controllers

How i can do button action for editing TableView . 我如何做按钮动作来编辑TableView I need to put text from TextArea to table when i touch button. 当我触摸按钮时,我需要将文本从TextArea放到表格中。 And if put System.out.println in inputToTable() it is work. 如果将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>

You load table.fxml twice: once via the fx:include in the main FXML file, and once in InputController , via the FXMLLoader you create in the tableControllerInit() method. 您加载table.fxml两次:通过一次fx:include主FXML文件,而一旦在InputController ,通过FXMLLoader您在创建tableControllerInit()方法。 Consequently, two instances of TableController are created, one associated with the first UI you load from table.fxml , and one associated with the second UI you load from table.fxml . 因此,的两个实例TableController被创建,一个具有从加载第一UI相关联table.fxml ,和一个与您从加载第二UI相关联table.fxml

The UI you load via the fx:include is displayed in the VBox defined in the main FXML file. 通过fx:include加载的UI将显示在主FXML文件中定义的VBox中。 The UI you load with the FXMLLoader is never displayed (in fact, you never even keep a reference to it, you just call loader.load() and discard the result). FXMLLoader加载的UI永远不会显示(实际上,您甚至从不保留对它的引用,只需调用loader.load()并丢弃结果)。 When you try to update the table's items (do you really intend to replace all the existing items, by the way?), you refer to the second controller instance, which is associated with the UI which is never displayed. 当您尝试更新表的项目(顺便说一句,您真的要替换所有现有项目吗?)时,您引用的第二个控制器实例与从未显示过的UI关联。 Consequently, you are updating a table that is not displayed, and you never see any results. 因此,您正在更新未显示的表,并且永远不会看到任何结果。

What you really need to do is share the same data between the two controllers associated with the two fx:include s. 您真正需要做的是在与两个fx:include关联的两个控制器之间共享相同的数据。 You can do this simply by injecting those two controllers into the main controller, as described in the "Nested Controllers" section in the documentation. 您可以简单地通过将这两个控制器注入到主控制器中来执行此操作,如文档中的“嵌套控制器”部分所述。

First, give the fx:include elements fx:id attributes: 首先,给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>

Then you can inject the controllers into the main controller by creating fields with the word "Controller" appended to the fx:id . 然后,您可以通过创建在fx:id后面附加单词"Controller"字段,将控制器注入到主控制器中。 Create a single observable list, which will represent the list of items displayed in the table, and pass it to each 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);
    }
}

Finally, just define the obvious methods in each of the other two controllers: 最后,只需在其他两个控制器中的每个中定义明显的方法:

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);
    }
}

Now the table is displaying the contents of the items list created in the main controller's initalize() method, and the InputController has a reference to the same list. 现在,该表显示了在主控制器的initalize()方法中创建的items列表的内容,而InputController引用了该列表。 So all you need to do is update that list in the InputController . 因此,您所需要做的就是更新InputController中的列表。 I assume you just want to add items to the table (not replace them all): 我假设您只想向表中添加项目(而不是全部替换):

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()));
        }
    }


}

More generally, if you have more data to share among the different controllers, you would create one or more "model" classes and share a model instance with the controllers. 更一般而言,如果您有更多的数据要在不同的控制器之间共享,则可以创建一个或多个“模型”类,并与控制器共享模型实例。 Then you can observe the properties of the model and update them. 然后,您可以观察模型的属性并进行更新。 See Applying MVC With JavaFx for a more comprehensive example. 有关更全面的示例,请参见将MVC与JavaFx一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM