【问题标题】:java swingworker not updating GUIjava swingworker没有更新GUI
【发布时间】:2013-04-21 16:39:08
【问题描述】:

问题基本上是我的 SwingWorker 没有做我想做的事情,我将在这里使用一些简化的代码示例,这些示例与我的代码相似,但没有令人讨厌的不相关细节。

在我的案例中我有两个课程:

  1. MainPanel 扩展 JPanel
  2. GalleryPanel 扩展了 JPanel

这个想法是 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 只能绘制该图像。

问候。

【问题讨论】:

    标签: java swing swingworker


    【解决方案1】:

    您对revalidate()repaint() 的调用是在GalleryPanel 有机会创建或添加之前即时发生的:

        @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();        
    

    【讨论】:

    • 非常感谢。这实际上是一个小错误,我认为从正常执行切换到后台执行时应该更加小心。
    • @Hovercraft Full Of Eels +1,但请确实(我的观点)好的做法是添加/删除/修改容器(重新验证和重新绘制)或其在工作线程中的 JComponents,
    • @mKorbel:同意。只有长时间运行的非 Swing 创建代码应该在工作线程中。
    • 有机会请accept回答。您还可以在此过程中查看您的一些 earlier questions
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多