javafx implementation of data transfer between controller s

Posted by bkbragg on Sun, 19 Jan 2020 07:04:47 +0100

Here are the contents of two posts: https://blog.csdn.net/u012880338/article/details/69063776   https://www.jianshu.com/p/6950b68970da

Communication between avafxcontrollers
Background:
Recently, I was finishing the design and needed to make things with JavaFX, but I didn't touch it before, so I had to start to do it. However, I can't find too much information when I found this thing. When I came across the menu and wanted to operate the page, I couldn't help it. After a long time of thinking and google, we finally found a way to celebrate.

Problem description
To create a new project in the application menu, you need to create a TreeView in the application project panel. However, the application menu and the engineering panel are not controlled by the same Controller, so operate directly. It is obvious that the program will report null pointer exception when running. Here is an example.
Catalog:

Next, the specific code of each file is given.

Main.java is relatively simple
Direct drawing


main.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainController">
   <top>
      <fx:include fx:id="menu" source="menu.fxml" />
   </top>
    <left>
        <fx:include fx:id="project" source="project.fxml" />
    </left>
</BorderPane>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
MainController.java
public class MainController implements Initializable {
    @FXML MenuController menuController;
    @FXML ProjectController projectController;
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        menuController.init(this);
        projectController.init(this);
    }

    public void addNewProject() {
        //projectController.addProject();
Treeitem mroot = new treeitem < >;
        for (int i = 0; i < 4; i++) {
TreeItem item = new TreeItem("module" + i);
            for (int j = 0; j < 3; j++) {
TreeItem t = new TreeItem("function point" + j);
                item.getChildren().add(t);
            }
            mRoot.getChildren().add(item);
        }
        projectController.mTreeView.setRoot(mRoot);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
menu.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.input.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>

<MenuBar xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MenuController">
  <menus>
    <Menu mnemonicParsing="false" text="File">
      <items>
        <MenuItem fx:id="newproject" mnemonicParsing="false" onAction="#newProjectClicked" text="New Project">
               <accelerator>
                  <KeyCodeCombination alt="UP" code="N" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
               </accelerator></MenuItem>
      </items>
    </Menu>
    <Menu mnemonicParsing="false" text="Edit">
      <items>
        <MenuItem mnemonicParsing="false" text="Delete" />
      </items>
    </Menu>
    <Menu mnemonicParsing="false" text="Help">
      <items>
        <MenuItem mnemonicParsing="false" text="About" />
      </items>
    </Menu>
  </menus>
</MenuBar>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
MenuController.java
public class MenuController {
    private MainController mainController;
    public void init(MainController controller) {
        mainController = controller;
    }

    public void newProjectClicked(ActionEvent event) {
        mainController.addNewProject();
    }
}
1
2
3
4
5
6
7
8
9
10
project.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>


<TreeView fx:id="mTreeView" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ProjectController" />
1
2
3
4
5
6
7
8
ProjectController.java
public class ProjectController {
    private MainController mainController;
    @FXML public TreeView mTreeView;
    public void init(MainController controller) {
        mainController = controller;
    }

    public void addProject() {
Treeitem mroot = new treeitem < >;
        for (int i = 0; i < 4; i++) {
TreeItem item = new TreeItem("module" + i, new ImageView(new Image(getClass().getResourceAsStream("model.png"))));
            for (int j = 0; j < 3; j++) {
TreeItem t = new TreeItem("function point" + j);
                item.getChildren().add(t);
            }
            mRoot.getChildren().add(item);
        }
        mTreeView.setRoot(mRoot);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
The above code writes to different MainController and ProjectController, but comments on one way.

summary
This is how JavaFX controllers communicate with each other. In this paper, two different controllers are communicated (one is commented). Communication between two controllers of the same level requires another Controller to act as mediator
It can be summarized as follows:
-In each independent Controller, you only need to know how to communicate with MainController.
-MainController requests specific Controller.
--------
Copyright notice: This is the original article of CSDN blogger "half life virtual Dang", following CC 4.0 BY-SA copyright agreement. Please attach the original source link and this notice for reprint.
Original link: https://blog.csdn.net/u012880338/article/details/69063776

 

Requirement Description:
Two fxml interfaces. When TextField is filled in the input box of one interface, click OK, and the content of TextField will be displayed in the Label of the other interface

Suppose that the controllers of the two interfaces are:
Resultcontroller (resultpage.fxml, the interface displaying results)
Inputcontroller (input string interface Input.fxml)

 
directory structure
  • First, define a data model AppModel.java

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class AppModel
{
    private StringProperty text = new SimpleStringProperty();

    public AppModel()
    {
        this.text = new SimpleStringProperty();
    }

    public StringProperty textProperty() {
        return text;
    }

    public final String getText() {
        return textProperty().get();
    }

    public final void setText(String text) {
        textProperty().set(text);
    }
}
  • Then, define an ApplModel instance in the interface controller ResultController to display the result, and bind the property listener in the initialization method

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class ResultController implements Initializable
{
    // static type required
    public  static AppModel model = new AppModel();
    @FXML
    private Label txtView;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // update text area if text in model changes:
        model.textProperty().addListener((obs, oldText, newText) -> txtView.setText(newText));
    }

    public static void setText(String text)
    {
        model.setText(text);
    }

    // Open text input window
    public void open(ActionEvent event) {
        // Select one from the template list
        try
        {
            Parent root = FXMLLoader.load(getClass().getResource("Input.fxml"));
            Stage stage = new Stage();
            stage.setTitle("Text entry window");
            stage.setScene(new Scene(root));
            stage.setFocused(true);
            stage.show();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }

}
  • In InputController interface of input content, call setText method of ResultController

import java.io.IOException;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;

public class InputController
{
    @FXML
    private TextField textEnter;

    // action event handler for button:
    @FXML
    private void sendText() {
        // Get result interface controller
        FXMLLoader loader = new FXMLLoader(getClass().getResource("ResultPage.fxml"));
        try
        {
            AnchorPane login = (AnchorPane) loader.load();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        ResultController control = (ResultController) loader.getController();
        // Set result interface content
        control.model.setText(textEnter.getText());
    }

    public void confirm(ActionEvent actionEvent)
    {
        //Change the template name list property of the template setting controller to trigger the observer
        String inputContent=textEnter.getText();
        ResultController.setText(inputContent);
        //close window
        ((Node) (actionEvent.getSource())).getScene().getWindow().hide();
    }

}

Attach interface code:
Input.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="180.0" prefWidth="210.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.InputController">
   <children>
      <TextField fx:id="textEnter" layoutX="14.0" layoutY="42.0" />
      <Button layoutX="14.0" layoutY="79.0" mnemonicParsing="false" onAction="#confirm" text="Determine" />
   </children>
</AnchorPane>

ResultPage.xml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="297.0" prefWidth="285.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ResultController">
   <children>
      <Label fx:id="txtView" layoutX="48.0" layoutY="46.0" prefHeight="34.0" prefWidth="135.0" text="result: " />
      <Button layoutX="48.0" layoutY="95.0" mnemonicParsing="false" onAction="#open" text="Open text input window" />
   </children>
</AnchorPane>

Program entry class Main.java


import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application
{
    @Override
    public void start(Stage primaryStage) {
        Parent root;
        try
        {
            root = FXMLLoader.load(getClass().getResource("ResultPage.fxml"));
            Scene scene = new Scene(root);
            primaryStage.setTitle("Data transfer between controllers");
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}


By: Mixqum
Link: https://www.jianshu.com/p/6950b68970da
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Topics: Programming Java xml encoding Google