java swingworker没有更新GUI

时间:2013-04-21 16:39:08

标签: java swing swingworker

基本上问题是我的SwingWorker没有按照我的意图去做,我会在这里使用一些简化的代码示例,它们与我的代码类似,但没有令人讨厌的不相关的细节。

我的案子中有两节课:

  1. MainPanel扩展JPanel
  2. GalleryPanel扩展JPanel
  3. 我们的想法是MainPanel是一个占位符类,并在运行时动态地向其添加其他JPanel(并删除旧的)。

    从MainPanel类中获取的代码:

    public void initGalleryPanel() {
        this.removeAll();
    
        double availableWidth = this.getSize().width;
        double availableHeight = this.getSize().height;
    
        double width = GamePanel.DIMENSION.width;
        double height = GamePanel.DIMENSION.height;
    
        double widthScale = availableWidth / width;
        double heightScale = availableHeight / height;
        final double scale = Math.min(widthScale, heightScale);
    
        add(new GalleryPanel(scale));
    
        revalidate();
        repaint();
    }
    

    这里的问题是创建GalleryPanel非常慢(> 1秒)我想显示一些加载圈并防止它阻止GUI,所以我把它更改为:

    public void initGalleryPanel() {
        this.removeAll();
    
        double availableWidth = this.getSize().width;
        double availableHeight = this.getSize().height;
    
        double width = GamePanel.DIMENSION.width;
        double height = GamePanel.DIMENSION.height;
    
        double widthScale = availableWidth / width;
        double heightScale = availableHeight / height;
        final double scale = Math.min(widthScale, heightScale);
    
        new SwingWorker<GalleryPanel, Void>() {
            @Override
            public GalleryPanel doInBackground() {
                return new GalleryPanel(scale);
            }
    
            @Override
            public void done() {
                try {
                    add(get());
                } catch (InterruptedException | ExecutionException ex) {
                    Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }.execute();        
    
        revalidate();
        repaint();
    }
    

    然而现在GalleryPanel不再出现了,任何帮助都会受到赞赏。

    额外信息:GalleryPanel的实例创建需要很长时间,因为它会呈现它应该在即时显示的内容,这样paintComponent只能绘制该图像。

    问候。

1 个答案:

答案 0 :(得分:5)

您对revalidate()repaint()的来电是在InstantPanel有机会创建或添加之前即刻发生的:

    @Override
    public void done() {
        try {
            add(get());
        } catch (InterruptedException | ExecutionException ex) {
            Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}.execute();        

revalidate();
repaint();

尝试在添加新组件后,在done()方法中进行调用:

    @Override
    public void done() {
        try {
            add(get());
            revalidate();
            repaint();
        } catch (InterruptedException | ExecutionException ex) {
            Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}.execute();