Swing Worker没有正确刷新JFrame

aus*_*ive 0 java swing jframe swingworker

我最初尝试在Java Action Listener中多次更新JFrame和JPanel,但两者都只会在Action Listener完成所有任务时更新.这是我原始问题的链接(在Action Listener中刷新JFrame).

我在反馈中被告知Swing Worker应该解决我的问题.但是,当我实现Swing Worker(如下所示)时,没有任何改变.仅当Action Listener完成所有任务时,JFrame和JPanel仍会更新.我的问题是,我错过了下面的内容吗?如果没有,我如何在Action Listener中实现它以及时正确更新Frame和Panel?

@Override
protected Integer doInBackground() throws Exception{
    //Downloads and unzips the first video.  
    if(cameraBoolean==true)
        panel.add(this.downloadRecording(camera, recording));
    else
        panel.add(new JLabel("Could not contact camera "+camera.getName()));

    panel.repaint();
    jframe.repaint();
    return 1;
}

private JLabel downloadRecording(Camera camera, Recording recording){
    //does a bunch of calculations and returns a jLabel, and works correctly
}

protected void done(){
    try{
        Date currentTime = new Timestamp(Calendar.getInstance().getTime().getTime());
        JOptionPane.showMessageDialog(jframe, "Camera "+camera.getName()+" finished downloading at "+currentTime.getTime());
    }catch (Exception e){
    e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

dic*_*c19 5

你对如何SwingWorker运作有误解.此类旨在提供在执行繁重任务时更新GUI的方法.所有这一切都是因为Swing组件更新发生在Event Dispatch Thread(又名EDT)中,这是一个特定的线程.

例如,如果您单击一个按钮并在EDT中执行所有耗时的任务,则此线程将阻止直到此任务完成.因此,您将看到您的GUI被冻结.

记住这一点,doInBackground()方法在另一个不是EDT的不同线程中运行.所以不要Swing在那里调用任何方法:

protected Integer doInBackground() throws Exception{
    //Downloads and unzips the first video.  
    if(cameraBoolean==true) // just use if(cameraBoolean), since this is a boolean
        panel.add(this.downloadRecording(camera, recording)); // NO!
    else
        panel.add(new JLabel("Could not contact camera "+camera.getName())); //NO!

    panel.repaint(); //NO, never!
    jframe.repaint();//NO, never!
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

执行之前添加一个JLabel,并使用publish()process()方法更新其文本:panel SwingWorker

JPanel panel = new JPanel();
final JLabel progressLabel = new JLabel("Some text before executing SwingWorker");
panel.add(progressLabel);

SwingWorker<Integer, String> worker = new SwingWorker<Integer, String>() {    
    @Override
    protected Integer doInBackground() throws Exception {
        if(cameraBoolean){
            pubish("Starting long process...");
            //Some processing here
            publish("Intermediate result to be published #1");
            //Some other processing stuff
            publish("Intermediate result to be published #2");
            //And so on...
            return 0;
        } else {
            publish("Could not contact camera "+camera.getName());
            return -1;
        }
    }

    @Override
    protected void process(List<String> chunks) {
        for(String string : chunks){
            progressLabel.setText(string);
        }
    }

    @Override
    protected void done() {
        progressLabel.setText("Finished!!!");
    }
};

worker.execute();
Run Code Online (Sandbox Code Playgroud)

两个process()done()方法都在EDT中进行,因此可以安全地进行GUI更新.看一下这个极好的例子:Swing Worker Example更多细节.