JavaFX控制器类不工作

JavaFX控制器类不工作,java,javafx,scenebuilder,Java,Javafx,Scenebuilder,我真的很难理解JavaFX控制器,我的目标是写一个TextArea作为日志 我的代码如下,但我希望能够更改另一个类的值等,我可以在需要时调用该类。我试图创建一个可初始化的控制器类,但无法使其工作。有人能把我引向正确的方向吗 我想将底部的@FXML代码移动到另一个类,它会更新场景 package application; import javafx.event.ActionEvent; import javafx.scene.control.Label; import javafx.scene.c

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

我的代码如下,但我希望能够更改另一个类的值等,我可以在需要时调用该类。我试图创建一个可初始化的控制器类,但无法使其工作。有人能把我引向正确的方向吗

我想将底部的@FXML代码移动到另一个类,它会更新场景

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);
    }
}

不要使应用程序类成为控制器。这是一种罪恶。还有其他问题和答案可以解决这个问题,但我的搜索技能目前无法找到它们

这是一种罪恶的原因是:

  • 您只应该有一个应用程序实例,并且在默认情况下,加载程序将生成一个新实例,因此您最终会得到两个应用程序对象
  • 引用成员对象令人困惑,因为原始启动的应用程序没有@FXML注入字段,但加载程序创建的应用程序实例有@FXML注入字段 另外,不相关的建议:在应用程序至少运行到显示UI的程度之前,不要开始尝试编写多线程代码

    JavaFX的多线程记录器就是答案,尽管不幸的是,它的实现并不直接,文档也很少


    textlogger/Root.fxml

    textlogger.WebImporter.java


    我可以让它显示出来并很好地工作,但我无法从我在线程中创建的类中计算出如何在文本区域中写作。当你不提供文本时,你会让我做更多的工作来帮助你解决问题。当你无法掌握一个概念时,很难完全解释它。是的,我知道,提出好的问题比写答案更难。希望这里的信息能对你有所帮助。谢谢你,你已经解决了我的问题。在没有人指导的情况下学习Java并非易事。我买的那本书《用Java开始为傻瓜编程》就是这么好。它教会我将应用程序类用作控制器。我以后不会这样做。我设法解决了如何在场景生成器中指定新控制器的问题。你帮助我学会了如何将TextArea解析到类中,这帮了我很多忙。我不理解“extends Task{”这个词,但我猜多态性或者是将类复制到自己的类中的一种方法。
    <?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;
        }
    }
    
    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);
        }
    }