gpt4 book ai didi

java - 更新 Swing 时等待线程

转载 作者:行者123 更新时间:2023-11-30 04:32:50 26 4
gpt4 key购买 nike

我在处理应用程序中的线程时遇到问题。它创建 JFrame 并启动一个新线程。最后一个将执行外部应用程序并更新 GUI。然后

我有问题让主类等待第二个线程完成,但同时更新 GUI。

这是我的示例(缩短):

class Main {

public int status;

public Main() {

// Creating GUI etc.

SwingUtilities.invokeLater(new Runnable() {

public void run() {
JDialog id = new JDialog();
id.button.addMouseListener(new MouseListener()); // Calls generate() method
}

});

}

public void generate() {

SwingUtilities.invokeLater(new Runnable() {

public void run() {
// Make changes to GUI
}

});

GeneratorThread genTest = new GeneratorThread(this, 1, 1, 1);
genTest.start();

//while (status == 0);

System.out.println("Next step.");

}

}

和线程类:

public class GeneratorThread extends Thread {

protected Main main;
protected int setSize, minValue, maxValue;

public GeneratorThread(Main main, int setSize, int minValue, int maxValue) {
this.main = main;
this.setSize = setSize;
this.minValue = minValue;
this.maxValue = maxValue;
}

public void run() {

// Execute program etc.
// Change GUI from main in the same time
// About 3 seconds

main.status = 1;

}

}

我正在进行中,我想检查到目前为止它是如何工作的。虽然工作得很好,但它以某种方式锁定了 Swing,并且只有当 GeneratorThread 完成时任何更改才可见。我想实时更新 GUI。

我尝试过join(),效果是一样的。我还尝试了 wait() (在 Main 上),但随后我得到了 IllegalStateMonitorException。

有什么提示吗?

最佳答案

Swing 是单线程环境。也就是说,有一个线程负责管理 Swing UI 的所有交互和更新 - 事件调度线程。

Swing 的黄金法则是......

  • 不要阻塞 EDT(Thread.sleepThread#joinObject#wait、阻塞 IO 和/或耗时任务(以及其他)永远不应该从 EDT 内调用),这样做会阻止 EDT 调度事件和绘制更新(以及其他)
  • 仅在 EDT 中创建/更新 Swing UI 元素。

这提出了一个问题...您如何“等待”线程?

最好的方法是使用观察者模式。基本上,您为 Thread 提供某种引用,它将调用该引用来提供事件通知,例如错误和完成...

这将要求您非常仔细地考虑应用程序的设计,因为您不能依赖于代码的简单 A 到 B 执行。

例如...

public class TestThreadCallBack {

public static void main(String[] args) {
new TestThreadCallBack();
}

public TestThreadCallBack() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public interface ThreadCallBack {

public void threadCompleted(Runnable source);

public void threadFailed(Runnable source);
}

public class TestPane extends JPanel implements ThreadCallBack {

private JLabel message;
private JLabel dots;
private int count;

private Timer timer;

public TestPane() {
setLayout(new GridBagLayout());
message = new JLabel("Running background task, please wait");
dots = new JLabel(" ");
add(message);
add(dots);

timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
count++;
if (count > 3) {
count = 0;
}
StringBuilder sb = new StringBuilder(3);
for (int index = 0; index < count; index++) {
sb.append(".");
}
for (int index = count; index < 3; index++) {
sb.append(" ");
}
dots.setText(sb.toString());
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();

Thread thread = new Thread(new BackgroundTask(this));
thread.start();

}

@Override
public void threadCompleted(Runnable source) {
timer.stop();
message.setText("Task completed successfully");
}

@Override
public void threadFailed(Runnable source) {
timer.stop();
message.setText("Task failed");
}
}

public class BackgroundTask implements Runnable {

private ThreadCallBack callBack;

public BackgroundTask(ThreadCallBack callBack) {
this.callBack = callBack;
}

@Override
public void run() {
System.out.println("Background task underway...");
try {
Thread.sleep(2000);
} catch (InterruptedException interruptedException) {
}
int result = (int) Math.round((Math.random() * 1));
if (result == 0) {
callBack.threadCompleted(this);
} else {
callBack.threadFailed(this);
}
}
}
}

除了 EDT 之外,从 Thread 内更新 UI 是很困惑的。一个更简单的解决方案实际上是使用 SwingWorker 。它具有发布/处理方法,可以轻松更新 UI 和进度方法,可用于提供有关当前任务进度的反馈。

您可以使用它的 done 方法在工作人员完成时通知感兴趣的各方。

关于java - 更新 Swing 时等待线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14221617/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com