java试图在模式对话框中更新JLabel
我有一个包含JLabel的模态对话框。此对话框调用另一个类中执行长时间运行的查找活动的方法。我希望这个查找类更新从模式对话框传递的JLabel
我尝试过在查找过程中从代码循环更新JLabel,也尝试过在计时器中更新JLabel。(我发现当模式对话框运行时,Swing计时器的actionPerformed方法从未被调用。)由于实现了计时器,我将查找过程移动到了一个单独的线程
我的查找工作正常,但直到过程结束,JLabel仍然不会重新绘制。如果有任何帮助,我将不胜感激
以下是相关的方法。DictionaryTuple是一个包含两个字段的POJO:一个列表和一个字符串。只有getter和setter,但dictionaryThread确实可以访问tupleList;请注意,在阅读完成之前,我们不会在此处触摸它
public List<DictionaryTuple> findTuples() {
tupleList = new ArrayList<DictionaryTuple>();
Thread dictionaryThread = new Thread(this); // This is the long-running lookup thread
dictionaryThread.start();
progressTimer = new Timer();
progressTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// progressCaption is updated in dictionaryThread
synchronized (progressCaption) {
lblProgress.setText(progressCaption);
}
lblProgress.repaint();
Thread.yield();
}
}, 250, 250);
try {
dictionaryThread.join();
} catch (InterruptedException e) {
} finally {
progressTimer.cancel();
lblProgress.setText("");
progressCaption = "";
}
return tupleList;
}
我也尝试过这种变化;在这种情况下,将保留内部run()调用,直到处理完成:
progressTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
synchronized (progressCaption) {
System.out.println("Fire!");
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Update");
lblProgress.setText(progressCaption);
lblProgress.repaint();
}});
}
}
}, 250, 250);
# 1 楼答案
这个演示应该会有帮助。如果我通过调用run来运行长作业,与在单独的线程中运行长作业相比,可以看到不同之处
# 2 楼答案
您需要准确地向我们显示您将对话框设置为可见的位置是在调用
findTuples()
方法之前还是之后?这是至关重要的建议:
# 3 楼答案
谢谢大家的建议。我实现的是气垫船,使用SwingWorker
我的方法所在的Dictionary类现在扩展了SwingWorker。findTuples()方法变成doInBackground()。计时器和我自己的线程代码不再是必需的
doInBackground()使用属性名为“progress”的publish()提供要在更新的JLabel中显示的文本
回到对话框代码中,调用涉及创建字典实例,并使用PropertyChangeListener处理JLabel(名为lblProgress)中的更改,以及检测处理何时完成:
我学会了不依赖SwingWorker。isDone()来确定SwingWorker的处理是否完成。在我的例子中,PropertyChangeListener在这种状态下被调用了两次:一次是最后一次publish()调用的结果,一次是任务实际完成时