控制器之间的JavaFx操作

时间:2017-09-25 23:00:01

标签: java javafx

如何为编辑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>

1 个答案:

答案 0 :(得分:2)

您加载table.fxml两次:一次是通过主要FXML文件中的fx:include,一次是InputController,通过您在FXMLLoader创建的tableControllerInit() } 方法。因此,创建了两个TableController实例,一个与您从table.fxml加载的第一个UI相关联,另一个与您从table.fxml加载的第二个UI相关联。

通过fx:include加载的UI显示在主FXML文件中定义的VBox中。您使用FXMLLoader加载的UI永远不会显示(事实上,您甚至不会保留对它的引用,只需调用loader.load()并丢弃结果)。当您尝试更新表的项目时(顺便说一下,您真的打算替换所有现有项吗?),您将引用第二个控制器实例,该实例与从未显示的UI相关联。因此,您正在更新未显示的表,并且您永远不会看到任何结果。

您真正需要做的是在与两个fx:include关联的两个控制器之间共享相同的数据。您可以通过将这两个控制器注入主控制器来完成此操作,如文档中的"Nested Controllers"部分所述。

首先,提供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>

然后,您可以通过创建"Controller"附加单词fx:id的字段将控制器注入主控制器。创建一个可观察列表,它将表示表中显示的项目列表,并将其传递给每个控制器:

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

现在,该表显示了在主控制器的items方法中创建的initalize()列表的内容,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()));
        }
    }


}

更一般地说,如果您在不同控制器之间共享更多数据,则可以创建一个或多个“模型”类并与控制器共享模型实例。然后,您可以观察模型的属性并更新它们。有关更全面的示例,请参阅Applying MVC With JavaFx