tags:

views:

1141

answers:

3

Clicking through JMenu options is causing my JOGL GLCanvas to flicker.

The JMenu has the setDefaultLightWeightPopupEnabled set to false. I don't want to use JGLPanel because it runs slower (the application needs to run in full screen mode).

Interesting, the flicker stops if I set sun.java2d.opengl=true on the command line. However, the fact that sun doesn't enable this by default makes me worry that I would risk my users having trouble with hardware incompatibilities.

Do other people see the flicker with the code below when clicking on the menu?

I've tried all sorts of things, such as playing with the double-buffering options for the JFrame and for the canvas, but had no luck getting the canvas to not flicker.

Can anyone get this not to flicker when the menu options are looked at?

Thanks!

-Dan

import javax.media.opengl.*;
import javax.swing.*;

public class FlickerTest extends JFrame {
    private GLCapabilities m_caps = new GLCapabilities();

    public FlickerTest() {
        super("FlickerTest");

        GLCanvas canvas = new GLCanvas(m_caps);
        add( canvas );
        canvas.addGLEventListener( new MyGLEventListener() );

        setSize( 640, 480 );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        // false lets the JMenuBar appear on top of the remote image openGL canvas
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);

        setJMenuBar( getMyMenuBar() );
        setVisible( true );
    }

    public static void main(String[] args) {
        new FlickerTest();
    }

    private static JMenuBar getMyMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem quitMenuItem = new JMenuItem( "Quit" );
        JMenuItem doSomething = new JMenuItem("Do Something");
        fileMenu.add( quitMenuItem );
        fileMenu.add( doSomething );

        menuBar.add( fileMenu );
        return menuBar;
    }

    private class MyGLEventListener implements GLEventListener {
        private MyGLEventListener() {
        }

        public void init(GLAutoDrawable drawable) {
            GL gl = drawable.getGL();
            gl.glClearColor(1,1,0,0);
            gl.glBlendFunc(GL.GL_ONE,GL.GL_ONE);
            gl.glEnable(GL.GL_BLEND);
        }

        public synchronized void display( GLAutoDrawable p_glAutoDrawable ) {
            GL gl = p_glAutoDrawable.getGL();

            gl.glClear(GL.GL_COLOR_BUFFER_BIT);

            gl.glColor3f(0,0,1);
            gl.glRectf(-.5f,-.5f,.5f,.5f);
            gl.glFlush();
        }

        public void reshape(GLAutoDrawable p_drawable, int x, int y, int w, int h) {
        }

        public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
        }
    }
}
+1  A: 

In the JFrame contructor, try calling createBufferStrategy(2);. This should enable DoubleBuffering in the JFrame.

Maudite
Wow, never even heard of that! Unfortunately, the flicker wasn't helped by that. Any other ideas?
A: 

You might want to add an animator. The canvas could be flickering because it isn't being refreshed fast enough by the JFrame.

FPSAnimator = new FPSAnimator(GLCanvas,int TARGET_FPS, boolean);
Maudite
Nah, it only flickers when the menu is selected/de-selected. This is independent of an animator, which only matters when you are displaying different images over time.
+1  A: 

This is caused by AWT erasing the GLCanvas every time before JOGL repaints it and can be worked around by inserting the following line into your main() method:

System.setProperty("sun.awt.noerasebackground", "true");

While this solves the given problem, side effects are possible in other areas of the application such as visible artifacts when resizing the window. I use this in all my JOGL apps though without any problems.

cgull