JavaFX Controller - 如何得到他

JavaFX Controller - how to get him

我在访问 Controller 时遇到问题。 我有一个包含两部分的主模板:菜单和主要内容 在两个单独的 FXML 文件中,我有菜单 (MenuTemplate.fxml) 和主要内容 (Content1Template.fxml)。 菜单和主要内容的加载正确进行

当Main Content 想要在按下按钮后更改文本时出现问题。 Content1Utils.java 必须在 Content1Controller.java 中设置文本。 我想我必须去控制器。我只是不知道该怎么做。

Link >> My Project in rar

Luncher.java

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import sample.main.MainController;

import java.io.File;
import java.net.URL;

public class Launcher extends Application {

    private static MainController mainController;

    @Override
    public void start(Stage primaryStage) throws Exception{
        URL mainTemplate = new File("src/sample/main/MainTemplate.fxml").toURI().toURL();

        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(mainTemplate);
        Parent root = loader.load();
        mainController = loader.getController();

        Scene scene = new Scene(root);

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

    public MainController getMainController(){
        return mainController;
    }
}

MainController.java

package sample.main;

import com.jfoenix.controls.JFXDrawer;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.VBox;
import java.io.File;
import java.io.IOException;
import java.net.URL;

public class MainController {

    @FXML private VBox rootBox;
    @FXML private JFXDrawer menuBox;
    @FXML private VBox contentBox;

    @FXML
    void initialize() throws IOException {
        URL menuTemplate = new File("src/sample/menu/MenuTemplate.fxml").toURI().toURL();
        VBox contentMenu = FXMLLoader.load(menuTemplate);
        menuBox.setContent(contentMenu);
    }

    public void changeContentBox(VBox content){
        contentBox.getChildren().setAll(content);
    }
}

MenuController.java

package sample.menu;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import sample.Launcher;
import sample.main.MainController;
import java.io.File;
import java.io.IOException;
import java.net.URL;

public class MenuController {

    @FXML private VBox menuRoot;
    @FXML private Button menuButton1;
    @FXML private Button menuButton2;
    @FXML private Button menuButton3;

    private MainController mainController;

    @FXML
    void initialize(){
    }

    public void clickButton1() throws IOException {
        URL content1Template = new File("src/sample/content1/Content1Template.fxml").toURI().toURL();
        VBox contentContent1 = FXMLLoader.load(content1Template);
        mainController = new Launcher().getMainController();
        mainController.changeContentBox(contentContent1);
    }

}

Content1Controller.java

package sample.content1;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;

public class Content1Controller {

    @FXML private VBox content1root;
    @FXML private Button content1Button;
    @FXML private TextArea content1TextArea;

    @FXML
    void initialize(){
    }

    public void content1Button(){
        Content1Utils contentUtils = new Content1Utils();
        contentUtils.prepareText("XXX");
    }

    public void setTextInArea(String txt){
        content1TextArea.setText(txt);
    }

}

Content1Utils.java

package sample.content1;

public class Content1Utils {

    public void prepareText(String txt){
        String newTxt = txt + " - Test123";
        new Content1Controller().setTextInArea(newTxt);
    }
}

MainTemplate.fxml

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

<?import com.jfoenix.controls.JFXDrawer?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>

<VBox fx:id="rootBox" prefHeight="442.0" prefWidth="665.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.main.MainController">
   <children>
      <HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" VBox.vgrow="ALWAYS">
         <children>
            <JFXDrawer fx:id="menuBox" style="-fx-background-color: #ebd534;" />
            <VBox fx:id="contentBox" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-background-color: #34b7eb;" HBox.hgrow="ALWAYS" />
         </children>
      </HBox>
   </children>
</VBox>

MenuTemplate.fxml

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>

<VBox fx:id="menuRoot" prefHeight="442.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.menu.MenuController">
   <children>
      <Button fx:id="menuButton1" maxHeight="100.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#clickButton1" text="Button 1" VBox.vgrow="ALWAYS" />
      <Button fx:id="menuButton2" maxHeight="100.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Button 2" VBox.vgrow="ALWAYS" />
      <Button fx:id="menuButton3" maxHeight="100.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Button3" VBox.vgrow="ALWAYS" />
   </children>
</VBox>

Content1Template.fxml

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>

<VBox fx:id="content1root" alignment="CENTER" prefHeight="442.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.content1.Content1Controller">
   <children>
      <Button fx:id="content1Button" contentDisplay="CENTER" mnemonicParsing="false" onAction="#content1Button" prefHeight="48.0" prefWidth="400.0" text="Button" textAlignment="CENTER">
         <VBox.margin>
            <Insets />
         </VBox.margin>
      </Button>
      <TextArea fx:id="content1TextArea" maxWidth="400.0" prefHeight="200.0" prefWidth="400.0">
         <VBox.margin>
            <Insets top="10.0" />
         </VBox.margin>
      </TextArea>
   </children>
</VBox>

错误

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.scene.Scene$MouseHandler.access00(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent3(GlassViewEventHandler.java:432)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null7(WinApplication.java:177)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
    ... 48 more
Caused by: java.lang.NullPointerException
    at sample.content1.Content1Controller.setTextInArea(Content1Controller.java:25)
    at sample.content1.Content1Utils.prepareText(Content1Utils.java:8)
    at sample.content1.Content1Controller.content1Button(Content1Controller.java:21)
    ... 58 more

问题出在这里:

public class Content1Utils {

    public void prepareText(String txt){
        String newTxt = txt + " - Test123";
        new Content1Controller().setTextInArea(newTxt);
    }
}

您正在创建一个未从 FXML 初始化的新控制器实例,因此它没有有效的 TextArea 字段。您不希望您的实用程序 class 以这种方式工作。

尝试:

public void content1Button(){
    Content1Utils contentUtils = new Content1Utils(this);
    contentUtils.prepareText("XXX");
}

Content1Utils.java:

package sample.content1;

public class Content1Utils {
    private final Content1Controller controller;

    public Content1utils(Content1Controller ctrl) {
        this.controller = ctrl;
    }

    public void prepareText(String txt){
        String newTxt = txt + " - Test123";
        controller.setTextInArea(newTxt);
    }
}