与我之前的问题相关:从 Java 中的另一个类调用重绘?
我是 Java 新手,我看过一些关于 SwingWorker 的教程。但是,我不确定如何使用我在上一个问题中提供的示例代码来实现它。
谁能解释一下如何在我的代码片段中使用 SwingWorker 和/或向我指出一个体面的教程?我看过,但我不确定我是否理解。
与我之前的问题相关:从 Java 中的另一个类调用重绘?
我是 Java 新手,我看过一些关于 SwingWorker 的教程。但是,我不确定如何使用我在上一个问题中提供的示例代码来实现它。
谁能解释一下如何在我的代码片段中使用 SwingWorker 和/或向我指出一个体面的教程?我看过,但我不确定我是否理解。
通常,SwingWorker 用于在 Swing 中执行长时间运行的任务。
在事件调度线程 (EDT) 上运行长时间运行的任务可能会导致 GUI 锁定,因此已完成的一件事是使用SwingUtilities.invokeLater
并invokeAndWait
保持 GUI 响应,从而在运行所需任务之前优先考虑其他 AWT 事件(以 a 的形式Runnable
)。
但是,问题SwingUtilities
在于它不允许将数据从执行的方法返回Runnable
到原始方法。这就是SwingWorker
旨在解决的问题。
Java 教程有一个关于SwingWorker的部分。
这是一个示例,其中 aSwingWorker
用于在单独的线程上执行耗时的任务,并在一秒钟后显示一个带有答案的消息框。
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);
}
应用程序运行后,将有两个按钮。一个标有“答案!” 和另一个“无”。当点击“答案!” 按钮,一开始什么都不会发生,但是单击“无”按钮将起作用并证明 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 的按钮,就无法移动鼠标。我错过了什么吗?