JProgressBar的setString不止一次

时间:2012-03-14 19:54:48

标签: java swing jprogressbar

我正在编写一个程序,它有两个主要阶段:确定感兴趣的区域,然后识别该区域中的对象。我的界面有一个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,但无济于事。那么,我该怎么做呢?

1 个答案:

答案 0 :(得分:4)

你必须明白,在你的

呼叫之间没有代码暂停(也不应该)
recognitionProgress.setString("Marking ROI...");

recognitionProgress.setString("Segmenting...");

除了第一位代码完成并到达第二位代码所需的毫秒数,并且两个后台任务可能同时发生。

解决此问题的选项包括:

  • 使用两个JProgressBars,每个任务一个,
  • 或从单个SwingWorker中运行这两个任务,以便两者都可以在同一个后台线程中完成并按顺序运行,
  • 或在第一个任务的属性更改侦听器之后运行第二个任务通知您第一个任务已完成(state属性返回SwingWorker.StateValue.DONE)。

如,

  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();
              }