与我之前的问题相关:Call repaint from another class in Java?
我是Java的新手,我已经看过一些关于SwingWorker的教程。然而,我不确定如何使用我在上一个问题中给出的示例代码来实现它。
任何人都可以解释如何使用SwingWorker关于我的代码片段和/或指向一个体面的教程吗?我看了,但我不确定我还明白。
答案 0 :(得分:105)
通常,SwingWorker用于在Swing中执行长时间运行的任务。
在事件调度线程(EDT)上运行长时间运行的任务会导致GUI锁定,因此所做的一件事就是使用SwingUtilities.invokeLater
和invokeAndWait
来保持GUI响应,在运行所需任务之前优先处理其他AWT事件(以Runnable
的形式)。
然而,SwingUtilities
的问题在于它不允许将执行的Runnable
中的数据返回到原始方法。这就是SwingWorker
旨在解决的问题。
Java Tutorial有一节关于SwingWorker。
以下是一个示例,其中SwingWorker
用于在单独的线程上执行耗时的任务,并在一秒钟后显示一个消息框并给出答案。
首先,将进行一个扩展SwingWorker
的课程:
class AnswerWorker extends SwingWorker<Integer, Integer>
{
protected Integer doInBackground() throws Exception
{
// Do a time-consuming task.
Thread.sleep(1000);
return 42;
}
protected void done()
{
try
{
JOptionPane.showMessageDialog(f, get());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
doInBackground
和get
方法的返回类型被指定为SwingWorker
的第一种类型,第二种类型是用于返回publish
的类型}和process
方法,在本例中未使用。
然后,为了调用SwingWorker
,调用execute
方法。在此示例中,我们将ActionListener
挂钩到JButton
以执行AnswerWorker
:
JButton b = new JButton("Answer!");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
new AnswerWorker().execute();
}
});
上面的按钮可以添加到JFrame
,然后点击以获取消息框。以下内容可用于初始化Swing应用程序的GUI:
private void makeGUI()
{
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new FlowLayout());
// include: "class AnswerWorker" code here.
// include: "JButton" b code here.
f.getContentPane().add(b);
f.getContentPane().add(new JButton("Nothing"));
f.pack();
f.setVisible(true);
}
运行应用程序后,会有两个按钮。一个标有“答案!”和另一个“没什么”。当点击“答案!”时按钮,一开始什么都不会发生,但点击“Nothing”按钮将起作用,并证明GUI是响应式的。
一秒钟之后,AnswerWorker
的结果将显示在消息框中。
答案 1 :(得分:7)
同意:
在事件调度线程(EDT)上运行长时间运行的任务可能导致GUI锁定。
不同意:
所以做的一件事就是使用SwingUtilities.invokeLater和invokeAndWait来保持GUI的响应......
invokeLater仍然在EDT上运行代码,并且可以冻结你的UI!试试这个:
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
至少我,一旦我点击触发上述代码的actionPerformed的按钮,就无法移动我的鼠标。我错过了什么吗?