In a short method, I hide a JFrame using setVisible(false). Then I take a screenshot and restore the JFrame with setVisible(true).
After made visible again, the window is supposed to show a different picture than before (lets say a part of that screenshot taken).
The problem is that after setVisible(true) is called, the window is flashed with the old content for a split second before paintComponent is called and the updated state is drawn.
I could probably workaround this in an ugly way, but I wanted to know if there are better solutions.
Thanks in advance for any help
edit: While preparing an example, I noticed that the effect was hardly ever observable when not using transparency like I do in my program. Should probably have mentioned that. Here is what I came up with:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.sun.awt.AWTUtilities;
public class Test {
static boolean flag = false;
static Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame();
frame.setUndecorated(true);
AWTUtilities.setWindowOpaque(frame, false); //draw on a transparent window
frame.setSize(scrSize.width, scrSize.height);
frame.setContentPane(new JPanel() {
protected void paintComponent(Graphics g)
{
if (Test.flag) {
g.setColor(Color.RED);
g.drawRect(50, 50, scrSize.width - 100, scrSize.height - 100);
}
else {
g.setColor(Color.GREEN);
g.fillOval(50, 50, scrSize.width - 100, scrSize.height - 100);
}
}
});
frame.setVisible(true); //green oval shown
Thread.sleep(1000);
frame.setVisible(false);
flag = true; // next draw produces red rectangle
Thread.sleep(1000);
frame.setVisible(true); // before the next draw,
// you can see a flash of the green oval
}
}
This is because each AWT window has an off-screen image that is kept in sync with the on-screen image. When a window is displayed, its contents are painted directly from the off-screen image. This happens on the toolkit thread, not on the event dispatch thread.
Only after the window is shown, the frame is repainted on the event dispatch thread.
Before Java 1.6, there was no per-window double buffering in the AWT, so you would have seen a gray background which was the infamous "gray rectangle" problem.
The only workaround I'm aware of is to create a new frame each time. You can reuse the content panel of the old frame, so the overhead is not so high.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With