0

When multiple JFrames are queued for repaint, the Swing Repaint Event paints the contents of all frames onto all frames, as though it is sharing the JPanels with the other frames.

In the example below, 'Frame 1' should only paint the square, and 'Frame 2' should only paint the oval. Instead, their graphics are somehow overlapping. The JPanels are not shared in any way, shape or form, so this should be impossible.

Swing Repaint


What I want to see is this:

Swing Repaint Desired

For some reason, this only happens when the frames are being drawn in a loop (e.g. at 60 FPS).

I'm running Java 1.8.0_25 on Windows 10 x64.

I've been at it for hours now, and I couldn't find anything online about this... Does anyone know of a way to avoid this issue? Or if there is a work-around?

Here's the code:

    JFrame frame1 = new JFrame("Frame 1");
    frame1.setSize(256, 256);
    frame1.setLocation(0, 0);
    JPanel panel1 = new JPanel() {
        public void paintComponent(Graphics g) {
            g.fillRect(32, 32, 32, 32);
        }
    };
    frame1.add(panel1);
    frame1.setVisible(true);

    JFrame frame2 = new JFrame("Frame 2");
    frame2.setSize(256, 256);
    frame2.setLocation(300, 0);
    JPanel panel2 = new JPanel() {
        public void paintComponent(Graphics g) {
            g.fillOval(66, 32, 32, 32);
        }
    };
    frame2.add(panel2);
    frame2.setVisible(true);

    while(true) {
        Thread.sleep(16);
        panel1.repaint();
        panel2.repaint();
    }

Solution (thanks MadProgrammer):

I did not add super.paintComponent(g) right after overriding the paintComponent() method. This fixed the issue. Unfortunately this also erases the previous graphics contents of the JPanel.

Roland
  • 612
  • 5
  • 17
  • 2
    Can not reproduce, using your exact code. Each panel shows just one shape. Using Java 1.8.0 on Xunbuntu 14.04 – tobias_k Oct 09 '15 at 10:01
  • 2
    1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) 3) Don't block the EDT (Event Dispatch Thread). The GUI will 'freeze' when that happens. See [Concurrency in Swing](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for details and the fix. 4) When custom painting, first call the super method to get the BG etc. – Andrew Thompson Oct 09 '15 at 10:01
  • 1) There's always a guy who posts this on every Stackoverflow question. It is minimal and complete. PM me how I can do it better. 2) This does not apply to me, I'm using this as a test because I will ultimately be using the Graphics2D engine, I'm not going to make a Swing-based UI, I only am using the JPanel to create my Graphics object (because Swing is quite efficient in that way). 3) I'm not blocking the EDT, I'm just calling two separate repaints within a very small time. The GUI does not freeze either. If you animate the code you'll see it works fine--it just duplicates across the frames. – Roland Oct 09 '15 at 10:08
  • 3
    You're not calling `super.paintComponent`, which is not clearing the, shared, `Graphics` context, which is screwing your updates welcome to "how to breaking painting 101", oh and no one is been "shared", the thing that connects the two panels is the `Graphics` context, which knows nothing about either of the panels, on that it should take what's painted to it and make it available on the screen – MadProgrammer Oct 09 '15 at 10:08
  • @MadProgrammer Thanks yes it works with `super.paintComponent()`, but that removes all the contents of the `JPanel`, similar to a `clearRect()`. Is there a way I can prevent this from happening? I'm trying to create a simple 'engine' using Graphics2D where I only repaint the parts of the screen that need to be repainted. – Roland Oct 09 '15 at 10:18
  • This is how painting works, when ever paintComponent is called, you are elected to repainted the entire state of the component – MadProgrammer Oct 09 '15 at 10:26
  • So my only way to fix this is to create my own back buffer image, and constantly draw that onto the JPanel? :/ – Roland Oct 09 '15 at 10:28
  • Well, swing is double buffeted by default, but it would depend on what you're trying to achieve. Remember, swing uses a passive rendering algorithm, meaning it can paint at any time – MadProgrammer Oct 09 '15 at 10:37
  • 1
    *"It is minimal and complete."* It is complete when it is in a class structure, includes imports and has a main method to run it. – Andrew Thompson Oct 09 '15 at 10:42

0 Answers0