Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在主线程中完成工作之前,线程中的progressbar不会更新其UI_Java_Swing_Progress Bar - Fatal编程技术网

Java 在主线程中完成工作之前,线程中的progressbar不会更新其UI

Java 在主线程中完成工作之前,线程中的progressbar不会更新其UI,java,swing,progress-bar,Java,Swing,Progress Bar,我正在将一个大文件切成块,并希望显示进度。 单击startCut按钮时,下面是要执行的代码: FileInputStream in = new FileInputStream(sourceFile); int blockSize = (int)(getSelectedBlockSize() * 1024); int totalBlock = Integer.parseInt(txtNumberOfBlock.getText()); byte[] buffer = new byte[blockSi

我正在将一个大文件切成块,并希望显示进度。 单击startCut按钮时,下面是要执行的代码:

FileInputStream in = new FileInputStream(sourceFile);
int blockSize = (int)(getSelectedBlockSize() * 1024);
int totalBlock = Integer.parseInt(txtNumberOfBlock.getText());
byte[] buffer = new byte[blockSize];
int readBytes = in.read(buffer);
int fileIndex = 1;

class PBThread extends Thread
{
    @Override
    public void run()
    {
        while(true)
        {
            pbCompleteness.setValue(value);
            //value++; //place A
            System.out.println(value);
            if (value >= 100)
                break;
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
        }
    }
}
value = 0;
PBThread pbThread = new PBThread();
pbThread.start();
while(readBytes != -1)
{
    File file = new File(targetFilePath + fileIndex);
    FileOutputStream out = new FileOutputStream(file);
    out.write(buffer, 0, readBytes);
    out.close();
    value = (int)(fileIndex / (double)totalBlock * 100);// place B
    readBytes = in.read(buffer);
    fileIndex++;
}
我在位置B的run方法之外更改了progressbar的值,问题是-grogressbar只显示两种状态:0%和100%。 但是,如果我去掉B处的代码,并在A处更改run方法中progressbar的值,问题就会消失。 我知道可能使用SwingWorker可以很容易地修复,但我确实想知道为什么会发生这种情况,尽管我在run方法中更改了值,但当我在run方法中打印出来时,它确实更改了。
在运行方法之外更改值时,如何解决该问题?

问题的关键在于您正在更新事件调度线程以外的线程上的组件:PBP完整性。您可以在运行方法中使用补救措施;e、 g

AtomicInteger value = new AtomicInteger(0);
while (true) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      pbCompleteness.setValue(value.get());
    }
  });

  // Do some work and update value.
}

这将导致在工作线程继续运行时,在事件调度线程上更新并重新绘制JProgressBar。注意,为了引用内部匿名可运行实例中的值,我将其更改为AtomicInteger。这也是可取的,因为它使线程安全。

这里有两个问题:

您正在Swing dispatcher线程中执行长时间运行的工作,这意味着您正在阻止它处理事件。尝试移动窗口等-它将失败。 你在A点从错误的线程更新UI。听起来你现在似乎没有受到影响,但这仍然是一个bug。
您应该使用SwingWorker或SwingUtilities来解决这两个问题。基本上,您不能从非UI线程访问UI,也不能在UI线程上执行长时间运行的工作。有关更多信息,请参阅。

我找到了一种解决此问题的非常简单的方法。您可以使用此代码并非常简单地处理此错误:

int progress=0;
Random random = new Random();
while (progress < 100) {
 //Sleep for up to one second.
 try {
       Thread.sleep(random.nextInt(100));
} catch (InterruptedException ignore) {}
progress+=1;
progressBar.setValue(progress);
Rectangle progressRect = progressBar.getBounds();//important line 
progressRect.x = 0;
progressRect.y = 0;         
progressBar.paintImmediately(progressRect);//important line 
 }

刚才,我了解了一些关于事件调度线程的知识,并且理解了您所说的,thx很多问题不是他正在更新EDT的Swing组件-这将导致NPE或可能的比赛条件。由于Swing被锁定,他正在调用EDT上的一段长时间运行的代码,可能是这一部分:whilereadBytes!=-1{…},它需要在后台线程中。我已经尝试了你的方法,仍然存在问题,我如何使用你的方法向你展示我的新代码?我如何向你展示我的新代码编辑问题,然后在每个问题的注释中通知回复者-让他们知道。我会记住你说的话。你帮了我很多忙。这很大程度上得益于你已经收到的好建议。。线程100;-不要那样做。如果GUI中需要延迟(例如用于动画),请创建一个Swing。