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

梦想与她 提交于 2021-02-16 21:19:09

问题


basically, I have this code which was initially working with console i/o now I have to connect it to UI. It may be completely wrong, I've tried multiple things although it still ends up with freezing the GUI.

I've tried to redirect console I/O to GUI scrollpane, but the GUI freezes anyway. 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.

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.

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.


回答1:


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. 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.

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.

This website provides a good example on how to use the SwingWorker class.




回答2:


As other answers pointed out, doing heavy work on the GUI thread will freeze the GUI. You can use a SwingWorker for that, but in many cases a simple Thread does the job:

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

Or if you use Java 8+:

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


来源:https://stackoverflow.com/questions/49671761/java-swing-gui-updating-changing-from-method-freezing-in-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!