简体   繁体   English

Java Swing GUI 更新/更改方法 - 循环冻结

[英]Java Swing GUI updating/changing from method - freezing in loop

basically, I have this code which was initially working with console i/o now I have to connect it to UI .基本上,我有这段代码,它最初与控制台 i/o 一起工作,现在我必须将它连接到UI It may be completely wrong, I've tried multiple things although it still ends up with freezing the GUI.这可能是完全错误的,我尝试了多种方法,尽管最终还是冻结了 GUI。

I've tried to redirect console I/O to GUI scrollpane, but the GUI freezes anyway.我试图将控制台 I/O 重定向到 GUI 滚动窗格,但 GUI 仍然冻结。 Probably it has to do something with threads, but I have limited knowledge on it so I need the deeper explanation how to implement it in this current situation.可能它必须对线程做一些事情,但我对它的了解有限,所以我需要更深入的解释如何在当前情况下实现它。

This is the button on GUI class containing the method that needs to change this GUI.这是 GUI 类上的按钮,包含需要更改此 GUI 的方法。

public class GUI {
 ...
btnNext.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {

                controller.startTest(index, idUser);

        }
    });
 }

This is the method startTest from another class which contains instance of Question class.这是来自另一个包含 Question 类实例的类的 startTest 方法。

public int startTest()  {

    for (int i = 0; i < this.numberofQuestions; i++) {
        Question qt = this.q[i];
            qt.askQuestion(); <--- This needs to change Label in GUI

        if(!qt.userAnswer())  <--- This needs to get string from TextField
            decreaseScore(1);    

    }

   return actScore();

}   

askQuestion method:问问题方法:

   public void askQuestion() {
    System.out.println(getQuestion());
    /* I've tried to change staticaly declared frame in GUI from there */


}   

userAnswer method:用户回答方法:

 public boolean userAnswer() {
    @SuppressWarnings("resource")
    Scanner scanner = new Scanner(System.in);

    if( Objects.equals(getAnswer(),userInput) ) {
        System.out.println("Correct");
        return true;
    }

    System.out.println("False");            
    return false;

}

Thanks for help.感谢帮助。

You're correct in thinking that it related to threads.您认为它与线程有关是正确的。

When you try executing code that will take a long time to process (eg. downloading a large file) in the swing thread, the swing thread will pause to complete execution and cause the GUI to freeze.当您尝试在 Swing 线程中执行需要很长时间处理(例如下载大文件)的代码时,Swing 线程将暂停以完成执行并导致 GUI 冻结。 This is solved by executing the long running code in a separate thread.这是通过在单独的线程中执行长时间运行的代码来解决的。

As Sergiy Medvynskyy pointed out in his comment, you need to implement the long running code in the SwingWorker class.正如Sergiy Medvynskyy在他的评论中指出的那样,您需要在SwingWorker类中实现长时间运行的代码。

A good way to implement it would be this:实现它的一个好方法是:

public class TestWorker extends SwingWorker<Integer, String> {

  @Override
  protected Integer doInBackground() throws Exception {
    //This is where you execute the long running
    //code
    controller.startTest(index, idUser);
    publish("Finish");
  }

  @Override
  protected void process(List<String> chunks) {
    //Called when the task has finished executing.
    //This is where you can update your GUI when
    //the task is complete or when you want to
    //notify the user of a change.
  }
}

Use TestWorker.execute() to start the worker.使用TestWorker.execute()启动工作器。

This website provides a good example on how to use the SwingWorker class.这个网站提供了一个关于如何使用 SwingWorker 类的很好的例子。

As other answers pointed out, doing heavy work on the GUI thread will freeze the GUI.正如其他答案所指出的,在 GUI 线程上做繁重的工作会冻结 GUI。 You can use a SwingWorker for that, but in many cases a simple Thread does the job:您可以为此使用SwingWorker ,但在许多情况下,一个简单的Thread完成这项工作:

Thread t = new Thread(){
    @Override
    public void run(){
        // do stuff
    }
};
t.start();

Or if you use Java 8+:或者,如果您使用 Java 8+:

Thread t = new Thread(() -> {
    // do stuff
});
t.start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM