基本上,问题是我的SwingWorker没有按照我的意愿去做,在这里我将使用一些简化的代码示例,这些示例与我的代码相似,但是没有讨厌的无关紧要的细节。

在我的情况下,我有两节课:


MainPanel扩展JPanel
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的速度很慢(>一秒钟),我想显示一些加载圆圈,并防止它阻塞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只能绘制该图像。

问候。

最佳答案

您对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();

09-05 00:26