Java Swing GUI 更新/更改方法 - 循环冻结 [英] Java Swing GUI updating/changing from method - freezing in loop

查看:38
本文介绍了Java Swing GUI 更新/更改方法 - 循环冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我有这段代码,最初用于控制台 i/o,现在我必须将其连接到 UI.这可能是完全错误的,我尝试了多种方法,尽管最终还是冻结了 GUI.

我尝试将控制台 I/O 重定向到 GUI 滚动窗格,但 GUI 仍然冻结.可能它必须对线程做一些事情,但我对它的了解有限,所以我需要更深入的解释如何在当前情况下实现它.

<块引用>

这是 GUI 类上的按钮,包含需要更改此 GUI 的方法.

公共类GUI {...btnNext.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {controller.startTest(index, idUser);}});}

<块引用>

这是来自另一个包含 Question 类实例的类的 startTest 方法.

public int startTest() {for (int i = 0; i < this.numberofQuestions; i++) {问题 qt = this.q[i];qt.askQuestion();<--- 这需要改变 GUI 中的标签if(!qt.userAnswer()) <--- 这需要从 TextField 获取字符串减少分数(1);}返回actScore();}

<块引用>

askQuestion 方法:

 public void askQuestion() {System.out.println(getQuestion());/* 我试图从那里改变 GUI 中静态声明的框架 */}

<块引用>

userAnswer 方法:

 public boolean userAnswer() {@SuppressWarnings("资源")扫描仪scanner = new Scanner(System.in);if( Objects.equals(getAnswer(),userInput) ) {System.out.println("正确");返回真;}System.out.println("假");返回假;}

感谢您的帮助.

解决方案

您认为它与线程有关是正确的.

当您尝试在 Swing 线程中执行需要很长时间处理(例如下载大文件)的代码时,Swing 线程将暂停以完成执行并导致 GUI 冻结.这是通过在单独的线程中执行长时间运行的代码来解决的.

正如 Sergiy Medvynskyy 在他的评论中指出的那样,您需要在 SwingWorker 类.

实现它的一个好方法是:

public class TestWorker extends SwingWorker{@覆盖受保护的整数 doInBackground() 抛出异常 {//这是你执行长时间运行的地方//代码controller.startTest(index, idUser);发布(完成");}@覆盖受保护的无效进程(列表<字符串>块){//当任务执行完成时调用.//这是您可以在何时更新GUI的地方//任务完成或你想要的时候//通知用户更改.}}

使用TestWorker.execute()来启动worker.

这个网站提供了一个关于如何使用的很好的例子SwingWorker 类.

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.

解决方案

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.

这篇关于Java Swing GUI 更新/更改方法 - 循环冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆