SwingUtilities.invokeLater()更新GUI时出现问题

Saa*_*ieh 3 java concurrency user-interface swing multithreading

我整天都在尝试这种不同的变化,但收效甚微.请有人帮忙解释一下我做错了什么?我只是一个关于线程的初学者.

private JTextArea text = new JTextArea();
private JButton button = new JButton("Cancel");
    public StatusFrame() {
        text.setEditable(false);
        this.add(text);
        this.add(button, BorderLayout.EAST);
        this.setSize(new Dimension(150, 100));
        this.setVisible(true);
    }

    public void updateStatus(String textIn) {
        text.setText(textIn);
    }

    public JButton getButton() {
        return button;
    }
Run Code Online (Sandbox Code Playgroud)

在另一个课程中,我正在调用可能需要一段时间才能完成的方法.我希望能够调用StatusFrame.updateStatus()方法来让用户了解进度.这就是我所拥有的:

someMethod() {
    // prevent GUI from freezing using threads
    final Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    SwingUtilities.invokeLater(r);

//do something 
    status.update("process 1 completed");
//do something else
    status.updateStatus("Process 2 completed");
}
Run Code Online (Sandbox Code Playgroud)

出现框架,但运行之后的代码似乎都没有运行/处理.它只是停止/阻止/某事.但GUI仍然有效

谢谢你的建议.

PS:我尝试过使用invokeAndWait()方法,但又不确定我是否采用了正确的方法.现在快速修复将是首选,因为我还没有学到很多关于线程的知识.欢迎任何指示.

Gil*_*anc 7

你有倒退的概念.

这是你的代码

someMethod() {
    // prevent GUI from freezing using threads
    final Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    SwingUtilities.invokeLater(r);

//do something 
    status.update("process 1 completed");
//do something else
    status.updateStatus("Process 2 completed");
Run Code Online (Sandbox Code Playgroud)

您应该在线程中执行长时间运行的代码,并使用SwingUtilities invokeLater方法更新GUI.

someMethod() {
    // prevent GUI from freezing using threads
    final Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    new Thread(r).start();

// inside the StatusFrame
//do something 
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            update("process 1 completed");
        }
    );

 //do something else sometime later
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
             update("Process 2 completed");
        }
    );
Run Code Online (Sandbox Code Playgroud)

我不知道我的回答是否清楚.

  1. 启动Java应用程序时执行SwingUtilities.invokeLater以确保Swing组件位于Event Dispatch线程(EDT)上.
  2. 从EDT,将长时间运行的进程作为可运行的线程调用.
  3. 在runnable线程中,由于您不在EDT上,因此每当您更新Swing组件时都要执行SwingUtilities.invokeLater.这可确保在EDT上更新Swing组件.

每个Swing应用程序都应该从这样的类开始:

import javax.swing.SwingUtilities;

import com.ggl.text.entry.model.TextEntryModel;
import com.ggl.text.entry.view.TextEntryFrame;

public class TextEntry implements Runnable {

    @Override
    public void run() {
        new TextEntryFrame(new TextEntryModel());
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TextEntry());
    }

}
Run Code Online (Sandbox Code Playgroud)

这堂课做了三件事.

  1. 构造GUI数据模型.
  2. 构造GUI JFrame.
  3. 确保Swing组件在EDT上.