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

Java JProgressBar在进程完成之前不会更新,java,swing,swingworker,event-dispatch-thread,jprogressbar,Java,Swing,Swingworker,Event Dispatch Thread,Jprogressbar,我知道这里有大量的JProgressBar问题,但通过所有的答案,我似乎无法诊断我的问题。我正在用地址验证软件处理一个文件。我单击“处理”按钮,需要使用我的JProgressBar更新处理的每个文件。 这是按钮: private JButton getJButton0() { ... jButton0.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) {

我知道这里有大量的
JProgressBar
问题,但通过所有的答案,我似乎无法诊断我的问题。我正在用地址验证软件处理一个文件。我单击“处理”按钮,需要使用我的
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();
}
编辑

这是我的
BulkProcessor
类中的代码

 private String getOutputLine( String searchString, String inputLine )
throws QasException
{
 ..(code for processing lines)..
 countRecord++;
    percentComplete = (int) Math.round((countRecord/totalRecord)*100);
 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();
    }

}
totalRecord
在my
BulkProcessor
类的主类中更新

 private String getOutputLine( String searchString, String inputLine )
throws QasException
{
 ..(code for processing lines)..
 countRecord++;
    percentComplete = (int) Math.round((countRecord/totalRecord)*100);
 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();
    }

}

看起来你在混合用法。请参阅SwingWorker文档,顶部的示例:

理想情况下,您应该使用SwingWorker的doInBackground方法更新BulkProcessor,这将调用setProgress,而jProgressBar将监听这些进度更新,如示例所示

如果这对你不起作用,这似乎不仅仅是基于上述,那么从按钮按下事件启动SwingWorker。实现类似这样的SwingWorker方法(伪代码):

newswingworker()
{
doInBackground()
{
做
{
percentComplete=BulkProcessor.getPercentComplete();
出版(竞争);
睡眠(100);
}完成率<100%;
}
@凌驾
流程(列出进度)
{
jProgressBar0.setValue(progress.get(0));
}
}.execute();

您需要添加错误处理和检查完整和失败案例,但这应该可以让您开始并达到您想要的目的。doInBackground在后台线程中运行,因此不会阻止任何内容,而process()在swing worker线程中运行,因此会发布更新。

您可能犯的错误是调用t.start();执行
jbutton0action后(事件)这使得执行操作后线程将启动。因此,进度条的值不会按预期更新

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

只是一种预感,但是

    percentComplete = (int) Math.round((countRecord/totalRecord)*100);
你确定这不是整数算术吗?我不知道totalRecord的类型,所以我不能肯定

我猜一切都很好,只是进度一直是0,直到完成,神奇地是100。这是因为一个整数除以一个整数将没有分数值(即99/100==0,100/100==1)。这完全符合你所经历的症状

尝试将上面的行替换为:

   percentComplete = (int) Math.round((countRecord/(double) totalRecord)*100);
看得出我是对的。:-)

您是否尝试过使用-界面

计算将由Swingworker线程完成,主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线程的“setProgress”方法,如果发生了什么事情,将通知主gui线程

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

Swing不是线程安全的。这不是最好的解决方案,但也许它可以帮助你。如果出现严重错误,请发表评论。

不要阻止EDT(事件调度线程)-发生这种情况时,GUI将“冻结”。不要调用
Thread.sleep(n)
为重复任务执行Swing
计时器,或为长时间运行的任务执行
SwingWorker
。有关更多详细信息,请参阅。。好的,这是我根据标题发表的评论。但是<代码>线程睡眠(100)在一个
SwingWorker
内?那是怪诞的化身!为了更快地获得更好的帮助,请发布一个。这是一个。请参阅上面的编辑,我基于Uwe Plonus的重复链接,一些在JTable标签下,这里有SwingWoker和Runnable@Threaddifferent类不是问题,只要线程正确交互,while循环中的%complete是指我的getPercentComplete()?另外,不需要返回类型吗?需要进行一些清理。我只是想抓住要点。您实际上不需要返回任何内容(尽管您确实需要返回类型,但是Void/null是有效的)。发布(整数)和进程(整数)是处理状态更新的主要方法。process()将实际获取列表,您只需要项0。是的,对于完成百分比,您需要知道何时停止检查和发布进度更新。但你大概有这个信息(检查进度<100只是一种方法)。在你的例子中,process方法从未被读取(查看我上一次编辑时使用的代码)查看我的编辑:1)将while循环更改为do while,在循环中读取大容量处理器值。2) 将@Override注释添加到process()方法中,以确保签名正确(应该是一个整数列表,您只关心第一个整数)。这一点您是对的,我之前确实了解到了这一点,但是我没有在我的帖子中更新它,抱歉。我已经完成了system.out.print(percentComplete)它在控制台中打印出我想要的值(1,3,4,5,…100)。所以我不相信这会是个问题。而且,totalRecord是一个双重记录