代码之家  ›  专栏  ›  技术社区  ›  Dan

如何使用JavaFX中的后台工作在GUI中进行更改?

  •  0
  • Dan  · 技术社区  · 7 年前

    从所有的搜索和阅读中,很明显我需要打电话 站台runLater() 更改GUI。似乎我还需要使用 可运行的 界面也许我也应该使用 任务 ?

    但我不知道我应该如何使用它们。另外,我不确定我应该把它们放在哪个班。我是JavaFX的新手。

    我的试用JavaFX项目只有一个标签和一个文本字段。标签包含一个问题,文本字段用于回答。很简单。

    我在这里遇到了问题:

    答案检查方法在单独的类中。我不知道如何访问GUI/FXML的组件并对其进行更改。其他类中的方法是静态的,而GUI/FXML的组件是非静态的。

    因为我的实际项目会有很多测验,所以我热衷于使用单独的课程来检查答案。

    此处仅涉及3个小班:

    1. 包含main方法的启动器类。
    2. FXML文件的ViewController类以及一些方法。
    3. –Ans–类,它有一个检查答案输入的方法。

    我应该把讲台放在哪一节课上。runLater()?代码是什么?

    我将只共享Ans和ViewController类的代码。

    Ans公司 (背景工作应该在这个文件中进行。在注释中,我提到了我想做但不能做的事情。例如,我想从那里设置标签文本,但我不能。因为我不知道如何做,所以我只在那里放了一个System.out.Println。在它旁边的注释中,我提到了我真正想做的事情。)

    package com.dan.ans;
    
    import com.dan.qn.Qn;
    import com.dan.view.ViewController;
    public class Ans {
    public static void checkAns() {
    
        // Checks if the ans is correct.
        if (ViewController.getTextFieldInput().equalsIgnoreCase(Qn.getAns())) {
    
            System.out.println("Correct!");     // Here I want the label to say 'Correct!' rather than it be print out in the console.
    
            Qn.setQuestion();                   // This gets the next question from the database. But again, I don't know how to make the changes show on the screen. (In the actual code I'd have a separate Label for each of these things)
    
        } else { // Runs if it's not correct.
    
            System.out.println("Incorrect!");    // Here I want the label to say 'Incorrect' rather than it be print out in the console.
        }
      }
    }
    

    视图控制器

    package com.dan.view;
    
    import java.io.IOException;
    import java.net.URL;
    import java.util.ResourceBundle;
    
    import com.dan.ans.Ans;
    import com.dan.qn.Qn;
    
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Label;
    import javafx.scene.control.TextField;
    
    public class ViewController implements Initializable {
    
    private static String textFieldInput;      // I don't know how to access the typed info in the textField from another class. So I store it here and get it from it.
    
    // This is the getter I use for it. (See above)
    public static String getTextFieldInput() {
        return textFieldInput;
    }
    
    @FXML
    private Label label;
    
    @FXML
    private TextField textField;
    
    @Override
    public void initialize(URL location, ResourceBundle resources) {
    
        Qn.setQuestion();                       // This method is in the Qn class. It retrieves data from the db file and keeps them in variables.
    
        label.setText(Qn.getQn());              // This sets the label's text using the retrieved data. So you see the first question when the program opens.
    }
    
    // Event Listener on TextField[#textField].onAction
    public void enter(ActionEvent event) throws IOException {
    
        textFieldInput = textField.getText();    // Stores the typed info in the variable to be accessed from elsewhere.
    
        Ans.checkAns();                         // Runs the checkAns to check if the typed answer is correct or not.
    
      }
    
    }
    

    Launcher方法看起来就像任何具有主类的方法。所以我没有在这里分享它的代码。

    有人能告诉我如何从其他类(如–Ans–Ans)更新GUI中的组件吗?我很确定我应该使用平台。runLater()和Runnable。也可能是任务。我已经看到了几个例子,但不清楚如何在这个上下文中使用它。

    提前非常感谢!:)

    1 回复  |  直到 7 年前
        1
  •  1
  •   James_D    7 年前

    现在还不太清楚到底是什么问题。(无论如何,对我来说)自然的方法就是 checkAnswer(...) 方法一种简单地“按框中的内容执行”的方法,即将答案作为参数,进行检查,并向调用者返回一个值,指示其是否正确。

    这样你也可以避免所有的丑陋 static 黑客。

    public class Ans {
    
        public boolean checkAns(String answer) {
            // not really sure what Qn is here, but you can also clean this up and
            // get rid of the static methods
            if (answer.equalsIgnoreCase(Qn.getAns()) {
                // not sure if this really belongs here?
                Qn.setQuestion(); // really takes no parameters? Sets it to what, then?
                return true ;
            } else {
                return false ;
            }
        }
    }
    

    然后在控制器中

    public class ViewController implements Initializable {
    
        private Ans ans ;
    
        @FXML
        private Label label;
    
        @FXML
        private TextField textField;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
    
            ans = new Ans();
            // ...
        }
    
        // ...
    
        public void enter(ActionEvent event) {
            if (ans.checkAns(textField.getText())) {
                // update UI to show answer was correct, etc
            } else {
                // update UI to show answer was incorrect...
            }
        }
    
        // ...
    }
    

    请注意这如何允许您保持适当的关注点分离: Ans 类不需要知道关于UI的任何信息(它根本不应该知道),所有特定于UI的代码都封装在它所属的控制器类中。

    不太清楚你为什么要问 Platform.runLater(...) 和使用 Task ,因为您发布的代码似乎都不涉及任何后台线程(也就是说,这些代码似乎都不会花费大量的时间来运行)。例如,如果 checkAns(...) 方法正在执行一些远程查找,并且确实需要时间运行,您可以在 任务 并从任务的 onSucceeded 处理程序。参见,例如。 Using threads to make database requests 。你的问题似乎更多的是关于基本的OO设计以及如何定义不同对象之间的关系;我认为你根本不是在问线程问题。