【问题标题】:Nested JavaFX Controller inside public class公共类中的嵌套 JavaFX 控制器
【发布时间】:2016-10-30 15:46:33
【问题描述】:

我有下面的代码,其中包含一个类和一个嵌套的JavaFX Controller。我初始化了 JavaFX 控制器类,我得到了它的一个实例,就像你看到的那样。

SpeechWindow 类:

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

import application.Main;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 * SpeechWindow
 *
 */
public class SpeechWindow extends Stage {

    private Container container = new Container();

    /**
     * Constructor
     */
    public SpeechWindow() {

        setTitle("SpeechResults");
        setScene(new Scene(container));
    }

    /**
     * @param text
     */
    public void appendText(String text) {
        container.appendText(text);
    }

    /**
     * 
     */
    public void clear() {
        container.clear();
    }

    public class Container extends BorderPane implements Initializable {

        @FXML
        private TextArea textArea;

        public Container() {
            // FXMLLOADER
            FXMLLoader loader = new FXMLLoader(getClass().getResource("SpeechWindow.fxml"));
            try {
                loader.load();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public void initialize(URL location , ResourceBundle resources) {
            System.out.println("Container has been initialized..");
        }

        public void appendText(String text) {
            Platform.runLater(() -> textArea.appendText(text + "\n"));
        }

        public void clear() {
            Platform.runLater(textArea::clear);
        }

    }

}

这是FXML代码

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

<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>


<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
   <center>
      <TextArea fx:id="textArea" editable="false" prefHeight="200.0" prefWidth="200.0" promptText="...no response" wrapText="true" BorderPane.alignment="CENTER" />
   </center>
</BorderPane>

尝试从 Main JavaFX Application 类中调用它,创建SpeechWindow 的实例并调用appendText(); 方法。为什么会出现空指针?

目标是:

然后我想在外部类中创建一个实例并使用它。


出了什么问题:

如果我创建 SpeechWindow 类的实例并调用方法 appendText(); 我得到空指针异常...为什么会发生这种情况,我看到一切都很好。我的错误是什么?

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    您永远不会将控制器实例连接到 fxml。

    使用setControllerFXMLLoader 设置控制器类。

    此外,您需要以某种方式将加载 fxml 的结果添加到场景中。可能您应该将 fxml 的根元素替换为 fx:root 元素。

    顺便说一句:如果实例无法使用,如果发生此类异常,简单地捕获加载异常似乎是个坏主意……

    public Container() {
        // FXMLLOADER
        FXMLLoader loader = new FXMLLoader(getClass().getResource("SpeechWindow.fxml"));
    
        // set controller & root
        loader.setController(this);
        loader.setRoot(this);
        try {
            loader.load();
        } catch (IOException ex) {
            // throw as cause of RuntimeException
            throw new IllegalStateException(ex);
        }
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.TextArea?>
    <?import javafx.scene.layout.BorderPane?>
    
    <fx:root type="javafx.scene.layout.BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
       <center>
          <TextArea fx:id="textArea" editable="false" prefHeight="200.0" prefWidth="200.0" promptText="...no response" wrapText="true" BorderPane.alignment="CENTER" />
       </center>
    </fx:root>
    

    【讨论】:

    • 哦,我怎么错过了,谢谢 Fabian!我会检查它是否有效,然后将其标记为答案...
    【解决方案2】:

    在调用其方法之前,您必须使用FXMLLoader.getController() 方法来获取您的Container 类。

    尝试调用

    FXMLLoader loader = new FXMLLoader(getClass().getResource(".../SpeechWindow.fxml"));
    

    来自SpeechWindow 类而不是Container 的构造函数。然后通过

    检索Container
    Container container = loader.getController();
    

    【讨论】:

    • 感谢 Cryptor 的努力,但在这里我想使用 fx:root,我错过了您可以在 Fabian 的回答中看到的内容。
    • 无论如何,这个答案不应该起作用,因为FXMLLoader没有创建控制器,因为fxml中没有指定fx:controller属性...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    • 2016-01-18
    • 1970-01-01
    相关资源
    最近更新 更多