我正在编写一个程序,它有两个主要阶段:确定感兴趣的区域,然后识别该区域中的对象。我的界面有一个JProgressBar,我希望它指出它目前正在进行的阶段。我注意到,通过简单的“线性”方法,只显示第二条消息。因此,在https://stackoverflow.com/a/277048之后,我使用Runnables和SwingUtilities.invokeLater来设置进度条的字符串。
private class MarkListener implements ActionListener {
public void actionPerformed(ActionEvent ae) {
mainFrame.getGlassPane().setCursor(new Cursor(Cursor.WAIT_CURSOR));
recognitionProgress.setStringPainted(true);
BlueMarkerTask bmt = new BlueMarkerTask();
bmt.addPropertyChangeListener(PrismRunnable.this);
SwingUtilities.invokeLater(new Runnable(){
public void run(){
recognitionProgress.setString("Marking ROI...");
}
});
bmt.execute();
RecognitionTask rt = new RecognitionTask();
rt.addPropertyChangeListener(PrismRunnable.this);
SwingUtilities.invokeLater(new Runnable(){
public void run(){
recognitionProgress.setString("Segmenting...");
}
});
rt.execute();
}
}
但是,这不起作用---只有“细分”仍保留在进度条的文本中。
我已经尝试过使用EventQueue而不是SwingUtilities,但无济于事。那么,我该怎么做呢?
答案 0 :(得分:4)
你必须明白,在你的
呼叫之间没有代码暂停(也不应该)recognitionProgress.setString("Marking ROI...");
和
recognitionProgress.setString("Segmenting...");
除了第一位代码完成并到达第二位代码所需的毫秒数,并且两个后台任务可能同时发生。
解决此问题的选项包括:
如,
public void actionPerformed(ActionEvent ae) {
mainFrame.getGlassPane().setCursor(new Cursor(Cursor.WAIT_CURSOR));
recognitionProgress.setStringPainted(true);
BlueMarkerTask bmt = new BlueMarkerTask();
bmt.addPropertyChangeListener(PrismRunnable.this);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
recognitionProgress.setString("Marking ROI...");
}
});
bmt.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (pcEvt.getPropertyName().equals("state")) {
if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
// you'd probably have this in a method.
RecognitionTask rt = new RecognitionTask();
rt.addPropertyChangeListener(PrismRunnable.this);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
recognitionProgress.setString("Segmenting...");
}
});
rt.execute();
}
}
}
});
bmt.execute();
}
修改强>
请注意,不需要在事件线程上对JProgressBar#setString(...)
方法进行排队,因为上面的所有代码都已经在事件线程EDT中。只有在当前代码被取消EDT时,或者在其他一些特殊情况下(这不是其中之一)时,才需要这样做。
所以你的代码看起来会更好:
// ** no need to queue this on the event thread.
// ** we're already IN the event thread!
recognitionProgress.setString("Marking ROI...");
bmt.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (pcEvt.getPropertyName().equals("state")) {
if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
// you'd probably have this in a method.
RecognitionTask rt = new RecognitionTask();
rt.addPropertyChangeListener(PrismRunnable.this);
// ** no need to queue this on the event thread.
// ** we're already IN the event thread!
recognitionProgress.setString("Segmenting...");
rt.execute();
}