Search code examples
javaswinganimationgraphics2d

Preventing RootPane repaint on GlassPane repaint


This question is similar to Paint on a glass pane without repainting other components. But I can't figure out how to apply the solution offered there.

My problem is that we have a very complicated RootPane, lots of components, and repainting it is expensive. We also have an animation running on the JFrame's GlassPane. I've noticed that every tick of the animation is repainting the animation as it should, but then also causing everything on the underlying RootPane to also be repainted.

I've tried overriding the paint() method for the RootPane with various code, but it always causes the components on the RootPane to be wiped and lots of flickering, probably from when child components try to repaint themselves as things update during the animation:

pnlContent = new JRootPane() {
   @Override
   public void paint(Graphics g) {
      OurGlassPaneWithAnimation glass = ...
      if (glass != null && glass.animation != null && glass.animation.isAlive()) {
         //Animation running, do something cool so root pane still looks good without repainting out the wazoo
      } else { super.paint(g); }
   }
};

Maybe putting the animation in a GlassPane is a bad idea? We've though about changing it to be in centered JPanel instead. Or is there a good way to do this using GlassPane and keeping the repaints done to the background RootPane to a minimum?


Solution

  • @MadProgrammer Thanks for the suggestion doing a repaint(rect) instead of just a repaint() solved the problem. Now we can crank up the animation fps as high as we want and it doesn't noticeably affect the load time of the RootPane behind it. Here's the code snippet.

    while (keepOnAnimating) {
       BufferedImage bi = vFrames.elementAt(0);
       if (bi != null) {
          // This only repaints area of image rect
          // Prevents lots of repaints from happening in rootpane behind glasspane.
          int x = getWidth() / 2 - bi.getWidth() / 2;
          int y = getHeight() / 2 - bi.getHeight() / 2;
          jc.repaint(x, y, bi.getWidth(), bi.getHeight());
      } else {
         jc.repaint();
      }
      ...
    }