我正在学习Swing并创建了一个示例GUI。我正在尝试按照确切的顺序实现以下目标......
我正在尝试使用invokeandwait,如下所示,但我得到“无法从事件调度程序线程调用invokeAndWait”。我的主要方法是在同一个.class文件中,我不太确定“事件调度程序线程”到底是什么。对于这样的事情最好的方法是什么,我是否需要在我的工作线程中设置某种警报以路由回“事件调度程序线程”?
LaunchButton代码
private void launchButtonActionPerformed(java.awt.event.ActionEvent evt) {
launchButton.setEnabled(false);
try {
java.awt.EventQueue.invokeAndWait(new MyTestThread());
} catch (Exception e) {
}
launchButton.setEnabled(true);
}
工作线程
public class MyTestThread extends Thread {
private int i = 0;
public void run() {
while (i < 5) {
try {
System.out.println(i++);
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
解决方案
工作线程
public class WorkerThread extends SwingWorker<Integer[], Void> {
@Override
public Integer[] doInBackground() {
System.out.println("Doing in background");
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
System.out.println("Doing in background" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public void done() {
System.out.println("Swingworker is Done");
}
}
从我的事件调度线程(EDT)启动工作线程
new WorkerThread().execute();
答案 0 :(得分:1)
事件调度线程(EDT)是唯一允许访问Swing类和(几乎所有)方法的线程。 GUI的所有初始化和事件都由EDT执行。要在EDT中执行某些操作,您必须使用SwingUtilities.invokeLater
或invokeAndWait
(这相当于EventQueue.invokeXXX
)。这就是所有Swing程序在main中以SwingUtilities.invokeLater()
开头的原因:在EDT中执行GUI初始化。
当EDT忙碌时,UI会冻结,这就是后台线程有用的原因。当你需要独立于UI(计算,I / O,传输......)进行大量工作时,你必须使用“工作线程”。
有关Swing中线程的更多信息,请参阅本教程:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
现在,你想要完成的是正确的,但你正在使用的工具不是。
您需要了解两件事:如何处理事件(如按钮按下)以及如何创建后台线程。
对于第一个,请参阅本教程: http://docs.oracle.com/javase/tutorial/uiswing/components/button.html
你只需要在按钮上添加一个ActionListener
,只要按钮抛出一个事件,就会在EDT中执行监听器的actionPerformed
方法。
最小例子:
JButton button = new JButton("Test button");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
System.out.println("The button was pressed.");
}
}
event
变量包含有用的信息,例如event.getSource()返回抛出事件的对象,在本例中为按钮。
现在,按下按钮时要执行的操作是创建工作线程。正如您在并发教程中看到的那样,使用SwingWorker类创建工作线程。在那里,您可以定义一段将在后台线程中执行的代码(在doInBackground()
方法中)和一段代码,这些代码将在后台工作完成后在EDT中执行(在{ {1}}方法)。
所以你想要做这样的事情:
done()
关于此,有很多信息。阅读类的Java参考,阅读官方教程并在SO中搜索。另一个关于SwingWorkers的好教程是:http://www.javacreed.com/swing-worker-example/