在进程完成之前,JProgressBar不会更新

时间:2013-06-13 14:13:15

标签: java swing swingworker event-dispatch-thread jprogressbar

我知道这里有大量JProgressBar个问题,但通过所有答案,我似乎无法诊断我的问题。我正在使用一些地址验证软件处理文件。我单击Process按钮,我需要JProgressBar更新每个处理过的文件。 这是按钮:

private JButton getJButton0() {
...
   jButton0.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
         jButton0ActionActionPerformed(event);
         t.start();
      }
...

根据每个人的建议,我在一个帖子中使用了setValue()方法

Thread t = new Thread(){
    public void run() {
    SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        jProgressBar0.setValue(BulkProcessor.getPercentComplete());
    }
});
try {
    Thread.sleep(100);
} catch (InterruptedException e) {
}
...

BulkProcessor.getPercentComplete()是我从另一个类调用的方法,表示完成百分比。我已经测试了这个方法,并且它正确更新。问题是进度条在文件处理完毕之前不会更新,然后它会跳转到100%。如果这是一个重复的问题,我道歉,但我在这个网站上做了一些严肃的挖掘而没有运气。任何帮助非常感谢。

修改:

根据推荐的重复,我试过这个:

public void update(){
   new SwingWorker<Void,Void>() {
   protected Void doInBackground() throws Exception {
   jProgressBar0.setValue(BulkProcessor.getPercentComplete());
   return null;
 };
 }.execute();
}

然后尝试在actionPerformed()下调用此update()方法(使用t.start()切换update())。我仍然有同样的问题。

修改

根据user1676075的建议,但同样的问题:

    public static void update(){
       new SwingWorker<Void,Integer>() {
       protected Void doInBackground() throws Exception {
           do
           {
           percentComplete = BulkProcessor.getPercentComplete();
           publish(percentComplete);
           Thread.sleep(100);
           } while(percentComplete < 100);

        return null;
       }
       @Override
    protected
       void process(List<Integer> progress)
       {
           jProgressBar0.setValue(progress.get(0));
       }
     }.execute();
   }

修改

以下是我的BulkProcessor

中的代码
 private String getOutputLine( String searchString, String inputLine )
throws QasException
{
 ..(code for processing lines)..
 countRecord++;
    percentComplete = (int) Math.round((countRecord/totalRecord)*100);

totalRecord在我的BulkProcessor班级

的主要班级中更新
 public static void main( String input, String output ){
    count.clear();
    try{
        String inputFile = input;
        String outputFile = output;
        LineNumberReader  lnr = new LineNumberReader(new FileReader(new File(input)));
        lnr.skip(Long.MAX_VALUE);
        totalRecord = lnr.getLineNumber() + 1; //line count in file
        BulkProcessor bulk = new BulkProcessor(inputFile, outputFile, ConfigManager.DFLT_NAME);
        bulk.process();
    }catch(Exception e ){
        e.printStackTrace();
    }

}

4 个答案:

答案 0 :(得分:0)

看起来你正在混合用法。请参阅顶部的SwingWorker文档示例:http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

理想情况下,您将在SwingWorker的doInBackground方法中更新BulkProcessor,并调用setProgress,jProgressBar将在示例中监听这些进度更新。

如果这对您不起作用,看起来它不仅仅基于上述内容,请从按钮按下事件启动SwingWorker。像这样实现SwingWorker方法(伪代码):

new SwingWorker<Void,Integer>()
{
  doInBackground()
  {
    do
    {
      percentComplete = BulkProcessor.getPercentComplete();
      publish(percentCompete);
      Thread.sleep(100);
    } while (percentComplete < 100);
  }

  @Override
  process(List<Integer> progress)
  {
     jProgressBar0.setValue(progress.get(0));
  }
}.execute();

您需要添加错误处理并检查完整和失败案例,但这应该可以帮助您入门并找到您想要的位置。 doInBackground在后台线程中运行,因此不会阻塞任何内容,并且process()在swing工作线程上运行,因此将发布更新。

答案 1 :(得分:0)

你可能犯的错误是调用t.start();在jButton0ActionPerformed(event);执行操作后执行该操作后,线程将启动。因此,进度条的值不会按预期更新。

你需要在jButton0ActionPerformed(event)中启动线程;然后更新其中的值。

答案 2 :(得分:0)

只是预感,但是......

    percentComplete = (int) Math.round((countRecord/totalRecord)*100);

你确定这不是整数运算吗?我不知道totalRecord的类型,所以我不能肯定地说。

我猜一切都运行正常,只是进度一直是0,直到神奇地为100完成。这是因为int除以int不会有分数值(即99/100 = = 0,100 / 100 == 1)。这非常适合您正在经历的症状。

尝试用以下代码替换上面的行:

   percentComplete = (int) Math.round((countRecord/(double) totalRecord)*100);

看到它我是对的。 : - )

答案 3 :(得分:0)

您是否尝试过使用PropertyChangeListener - 界面?

计算将由Swingworker线程完成,main-gui将实现此接口。一些示例代码

@Override
public void actionPerformed(ActionEvent e) {
    this.myButton.setEnabled(false);
    MyWorkerThread thread = new MyWorkerThread(); //Data-processing
    thread.addPropertyChangeListener(this.mainguiframe); //Separation of concern
    thread.execute();
}

使用swing-worker-thread的“setProgress”方法,如果发生了某些事情,将通知main-gui-thread。

@Override
public void propertyChange(PropertyChangeEvent property) {
     Integer currentValue = new Integer(0);
     currentValue = (Integer) property.getNewValue();
     this.progressBar.setValue(currentValue.intValue());
}

Swing不是线程安全的。这不是最好的解决方案,但也许它可以帮到你。如果有可怕的错误,请评论。