skiwi
skiwi

Reputation: 69259

java swingworker not updating GUI

Basicaly the problem is that my SwingWorker is not doing what I intend it to do, I will use some simplified code examples in here which are similar to my code but without the nasty non-relevant details.

I got two classes in my case:

  1. MainPanel extending JPanel
  2. GalleryPanel extending JPanel

The idea is that the MainPanel is a placeholder class and dynamically on runtime I add other JPanel's to it (and remove the old one).

The code that does work, taken from inside MainPanel class:

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

The problem here is that creating the GalleryPanel is quite slow (> one second) and I would like to display some loading circle plus prevent it from blocking the GUI, so I changed it to this:

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

However now the GalleryPanel does not show up anymore, any help would be appreciated.

Extra info: The GalleryPanel's instance creation takes so long because it renders what it should show at instantition, such that the paintComponent can merely paint that image.

Regards.

Upvotes: 1

Views: 1048

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

Your calls to revalidate() and repaint() occur instantaneously and before the GalleryPanel has had a chance to be created or added:

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

revalidate();
repaint();

Try instead making those calls from within the done() method, after you've added the new component:

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

Upvotes: 5

Related Questions