当前位置: 首页 > 知识库问答 >
问题:

JavaFX控制器类不工作

壤驷高旻
2023-03-14

我真的很难理解JavaFX控制器,我的目标是写一个TextArea来充当日志

我的代码在下面,但我希望能够改变值等从另一个类,我可以调用时需要。我试图创建一个扩展初始化的控制器类,但我无法使它工作。有谁能指引我正确的方向吗?

package application;
import javafx.event.ActionEvent;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
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) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("Root.fxml"));
            Scene scene = new Scene(root,504,325);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

    public Thread thread = new Thread(new webimporter());

    @FXML
    public Label runningLabel;

    @FXML 
    public TextArea txtArea;

    @FXML
    void runClick(ActionEvent event) throws IOException{
        changeLabelValue("Importer running...");
        thread.start();

    }   

    @FXML
    protected void stopClick(ActionEvent event){
        changeLabelValue("Importer stopped...");
        thread.interrupt();
    }           

    @FXML
    void changeLabelValue(String newText){
        runningLabel.setText(newText);
    }

    void changeTextAreaValue(String newText1){
        txtArea.setText(newText1);
    }
}

共有1个答案

江嘉悦
2023-03-14

不要使应用程序类成为控制器。这是罪过。还有其他的问题和答案来解决这个问题,但是我的搜索技巧在这个时候找不到它们。

它是罪过的原因是:

  1. 您应该只有一个应用程序实例,并且默认情况下,加载程序将生成一个新实例,因此您将得到两个应用程序对象。
  2. 引用成员对象很混乱,因为最初启动的应用程序没有@fxml注入字段,但加载器创建的应用程序实例有@fxml注入字段。
<?xml version="1.0" encoding="UTF-8"?>

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

<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="400.0" spacing="10.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="textlogger.ImportController">
   <children>
      <HBox alignment="BASELINE_LEFT" minHeight="-Infinity" minWidth="-Infinity" spacing="10.0">
         <children>
            <Button mnemonicParsing="false" onAction="#run" text="Run" />
            <Button mnemonicParsing="false" onAction="#stop" text="Stop" />
            <Label fx:id="runningLabel" />
         </children>
         <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
         </padding>
      </HBox>
      <TextArea fx:id="textArea" editable="false" prefHeight="200.0" prefWidth="200.0" />
   </children>
   <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
   </padding>
</VBox>
package textlogger;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;

import java.io.IOException;

public class ImportController {
    @FXML
    private Label runningLabel;

    @FXML
    private TextArea textArea;

    private WebImporter importer;

    @FXML
    void run(ActionEvent event) throws IOException {
        changeLabelValue("Importer running...");

        if (importer == null) {
            importer = new WebImporter(textArea);
            Thread thread = new Thread(
                    importer
            );
            thread.setDaemon(true);
            thread.start();
        }
    }

    @FXML
    void stop(ActionEvent event){
        changeLabelValue("Importer stopped...");
        if (importer != null) {
            importer.cancel();
            importer = null;
        }
    }           

    private void changeLabelValue(String newText){
        runningLabel.setText(newText);
    }

}
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.scene.control.TextArea;

import java.time.LocalTime;

public class WebImporter extends Task<Void> {

    private final TextArea textArea;

    public WebImporter(TextArea textArea) {
        this.textArea = textArea;
    }

    @Override
    protected Void call() throws Exception {
        try {
            while (!isCancelled()) {
                Thread.sleep(500);

                Platform.runLater(
                        () -> textArea.setText(
                                textArea.getText() + LocalTime.now() + "\n"
                        )
                );
            }
        } catch (InterruptedException e) {
            Thread.interrupted();
        }

        return null;
    }
}

TextLogger.TextLoggingSample.java

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

public class TextLoggingSample extends Application {
    @Override
    public void start(Stage stage) {
        try {
            FXMLLoader loader = new FXMLLoader();
            Parent root = loader.load(
                getClass().getResourceAsStream(
                        "Root.fxml"
                )
            );

            Scene scene = new Scene(root);
            stage.setScene(scene);
            stage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
 类似资料:
  • 我在Scene Builder中为Eclipse中的JavaFX项目创建了一个非常简单的fxml。当我尝试运行它时,由于未找到controller类,我得到了LoadException。 附加的包资源管理器和错误的截图 如果你能告诉我是什么原因造成这个问题,我将不胜感激。

  • 嗨,我正在构建JavaFX项目,我正在使用JavaFX Scene Builder2。我想将我的控制器链接到我的fxml文件,但是我看不到在Scene Builder2中添加控制器到我的fxml文件的可能性。我在想是否有人能帮我一下。谢谢你。

  • 我正在学习使用SceneBuilder创建一个新的JavaFX应用程序的教程,并尝试向.fxml文件添加一个controller类。 我正在使用Eclipse和Gluon的Scene Builder V8.1.1版本。 在哪里可以将我的.fxml文件连接到我的控制器Java类?

  • 问题内容: 有什么方法可以从关联的类控制器获取FXML加载文件的Scene对象。 我正在做这样的事情: 但是我想要一个不引用AnchorPane控件的解决方案。 问题答案: 为什么不?Controller是一个抽象类,除非您有意让他知道,否则他不了解UI。 节点(包括AnchorPane)是另一个故事,它们几乎不存在于场景图的外部。因此,最好向Node询问有关其父母或场景的信息。 如果您仍然想单独

  • 但我想要一个不引用AnchorPane控件的解决方案。