【问题标题】:How can I access the controller of a parent component from its child component? JavaFX 8如何从子组件访问父组件的控制器? JavaFX 8
【发布时间】:2020-04-16 23:54:23
【问题描述】:

我正在尝试使用 FXML 在 JavaFX 中构建 GUI。为此,我有一个 FXML 主页面,其中包含 3 个我也使用 FXML 创建的自定义组件。这是我的代码目录:

src
   App.java
   ui
      MainView.java
      CustomHeader.java
      CustomBody.java
   fxml
      MainView.fxml
      CustomHeader.fxml
      CustomBody.fxml
   controller
      MainViewController.java
      CustomHeaderController.java
      CustomBodyController.java

App.java

package ui;

import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import model.main.TaskItem;

import java.time.LocalDateTime;
import java.util.ArrayList;

public class ProductivityTrackerApp extends Application {
    public static Stage primaryStage;
    public static final String TITLE = "App";
    public static final double WIDTH = 520;
    public static final double HEIGHT = 800;

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

    public void setPrimaryStage(Stage primaryStage) {
        this.primaryStage = primaryStage;
    }

    public static void setScene(Parent root) {
        try {
            Scene scene = new Scene(root, WIDTH, HEIGHT);
            primaryStage.setTitle(TITLE);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            System.out.println("Failed to load new Scene!");
        }
    }
    @Override
    public void start(Stage primaryStage) throws Exception {
        setPrimaryStage(primaryStage);
        setScene(new MainView());
    }
}

Main.fxml

<fx:root xmlns="http://javafx.com/javafx"
         xmlns:fx="http://javafx.com/fxml"
         fx:controller="controllers.MainController"
         fx:id="root"
         type="VBox">

    <children>
         <CustomHeader> </CustomHeader>
         <CustomBody> </CustomBody>
    </children>
</fx:root>

MainView.java

package ui;

import javafx.fxml.FXMLLoader;
import javafx.scene.layout.VBox;

import java.io.File;
import java.io.IOException;

public class MainView extends VBox {

    private static final String FXML = "src/fxml/MainView.fxml";
    private File fxmlFile = new File(FXML);

    public MainView() {
        this.load();
    };

    private void load() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(fxmlFile.toURI().toURL());
            fxmlLoader.setRoot(this);
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

CustomHeader.fxml

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

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

<fx:root xmlns="http://javafx.com/javafx"
         xmlns:fx="http://javafx.com/fxml"
         fx:controller="controllers.CustomHeaderController"
         minHeight="80.0" prefWidth="520.0" type="StackPane">

<BorderPane>
    <left>

    </left>

    <center>
        <Label text="App"/>
    </center>

    <right>
       <Button text="Click here" onMouseClicked="#colorBody"/>
    </right>
</BorderPane>
</fx:root>

CustomHeader.java

package ui;

import javafx.fxml.FXMLLoader;
import javafx.scene.layout.StackPane;

import java.io.File;
import java.io.IOException;

public class MainView extends StackPane {

    private static final String FXML = "src/fxml/CustomHeader.fxml";
    private File fxmlFile = new File(FXML);

    public CustomHeader() {
        this.load();
    };

    private void load() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(fxmlFile.toURI().toURL());
            fxmlLoader.setRoot(this);
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

CustomBody.fxml


<fx:root xmlns="http://javafx.com/javafx"
         xmlns:fx="http://javafx.com/fxml"
         fx:controller="controllers.CustomBodyController"
         type="StackPane">

   <Rectangle width="240" height="240" StackPane.alignment = "CENTER"/>
</fx:root>

CustomBody.java

package ui;

import javafx.fxml.FXMLLoader;
import javafx.scene.layout.StackPane;

import java.io.File;
import java.io.IOException;

public class MainView extends StackPane {

    private static final String FXML = "src/fxml/CustomBody.fxml";
    private File fxmlFile = new File(FXML);

    public CustomBody() {
        this.load();
    };

    private void load() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(fxmlFile.toURI().toURL());
            fxmlLoader.setRoot(this);
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

控制器还没有任何功能。因此,我没有包括它们。

我想引入一个功能,即在 CustomHeader 组件中的按钮上的 onClick 操作会改变 CustomBody 组件中矩形的颜色。但是,由于这些组件有单独的控制器,我想知道是否有办法让我从 MainController(父组件的控制器)访问这两个控制器。此外,如果可能,是否有更好的建议来调解两个兄弟组件的通信?

【问题讨论】:

标签: user-interface javafx javafx-8


【解决方案1】:
<CustomHeader fx:id="customHead"> </CustomHeader>

在fxm文件中添加一个变量

public CustomHead customHead;

在 MainController 中。

【讨论】:

  • 我不知道如何使用它。如果在 CustomHeader 组件中发生了一个动作,如何使用它来更改为 CustomBody 组件?也许,我添加的代码示例会让我想说的更清楚?
  • 我还是建议你使用控制器而不是托管节点
  • 只需将 fx:id 添加到 CustomHeader 和 CustomBody。您现在可以在两个组件上调用公共方法
猜你喜欢
  • 2018-01-16
  • 2018-04-02
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多