如何在Java中使用SwingWorker?
与我以前的问题相关: 从Java中的另一个类调用repaint? 。
我是新来的Java,我已经看了一些关于SwingWorker的教程,但我不确定如何使用上一个问题给出的示例代码来实现它。
任何人都可以解释如何使用SwingWorker与我的一点点的代码,或者指向我一个体面的教程,请? 我看了,但我不知道我明白了。
通常,SwingWorker用于在Swing中执行长时间运行的任务。
在事件调度线程(EDT)上运行长时间运行的任务会导致GUI被锁住,所以完成的一件事情就是使用SwingUtilities.invokeLater
和invokeAndWait
,它保持了GUI的响应,从而优先处理其他的AWT事件运行所需的任务(以Runnable
的形式)。
但是, SwingUtilities
的问题是它不允许从执行的Runnable
返回到原始方法的数据。 这就是SwingWorker
设计目标。
Java教程有一个关于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
的结果将出现在消息框中。
同意:
在事件调度线程(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与上面的代码。 我错过了什么吗?