GLCanvas - draw a default background while rendering

In my application I have to add and remove a GLCanvas to my GUI a few times. After I add a GLCanvas to my GUI
I need to recreate my textures and stuff which takes some time. The problem is that meanwhile, my GLCanvas
shows a portion of my screen instead of a white/black background until my first display() call is done, so that makes
things really ugly.

complete testcase to illustrate the problem. press button 1 first, then button2:


import java.awt.*;
import java.awt.event.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
import javax.swing.*;

public class Main extends JFrame implements GLEventListener {
    private JPanel pnlContents = new JPanel();
    private GLCanvas canvas1 = new GLCanvas();
    private GLU glu = new GLU();
    
    public Main() {
        this.setLayout(new BorderLayout());
        
        canvas1.addGLEventListener(this);

        JPanel pnlMenu = new JPanel();
        JButton btn1 = new JButton("1");
        btn1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setPanel1();
            }
        });
        pnlMenu.add(btn1);
        JButton btn2 = new JButton("2");
        btn2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setPanel2();
            }
        });
        pnlMenu.add(btn2);
        
        pnlContents.setLayout(null);
        this.getContentPane().add(pnlMenu, BorderLayout.WEST);
        this.getContentPane().add(pnlContents, BorderLayout.CENTER);
    }
    
    public void setPanel1(){
        pnlContents.setBackground(Color.YELLOW);
        pnlContents.removeAll();
        JLabel lbl = new JLabel("test label button 1");
        lbl.setBounds(100, 100, 200, 20);
        pnlContents.add(lbl);
    }
    
    public void setPanel2(){
        pnlContents.setBackground(Color.RED);
        pnlContents.removeAll();
        canvas1.setBounds(100, 100, 800, 600);
        pnlContents.add(canvas1, BorderLayout.CENTER);
    }
    
    public void init(GLAutoDrawable gLAutoDrawable) {
        GL gl = gLAutoDrawable.getGL();
        gl.glDisable(GL.GL_DEPTH_TEST);
        gl.glClearColor( 0, 0, 0, 0 );
    }
    
    public void display(GLAutoDrawable gLAutoDrawable) {
        GL gl = gLAutoDrawable.getGL();
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glClear(GL.GL_COLOR_BUFFER_BIT);

        gl.glColor4f( 0, 1, 0, 1 );
        gl.glBegin(gl.GL_QUADS);
        gl.glVertex2f(0, this.getHeight()); //SW
        gl.glVertex2f(0, 0); //NW
        gl.glVertex2f(this.getWidth(), 0); //NE
        gl.glVertex2f(this.getWidth(), this.getHeight()); //SE
        gl.glEnd();
        
        try{Thread.sleep(4000);}catch(Exception e){}
    }
    
    public void reshape(GLAutoDrawable gLAutoDrawable, int x, int y, int w, int h) {
        GL gl = gLAutoDrawable.getGL();
        gl.glViewport( 0, 0, w, h );
        gl.glMatrixMode( GL.GL_PROJECTION );
        gl.glLoadIdentity();
        glu.gluOrtho2D( 0.0, w, h, 0.0); //flip y axis !
    }
    
    public void displayChanged(GLAutoDrawable gLAutoDrawable, boolean b, boolean b0) {
    }
    
    public static void main(String[] args) {
        JFrame frm = new Main();
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frm.setSize(1024, 768);
        frm.setVisible(true);
    }
}

Try calling gl.glClear(GL.GL_COLOR_BUFFER_BIT); in init() and resize().

too bad, that’s not the solution

Why do you need to add and remove the GLCanvas a couple of times in your program?

I have two GLCanvas instances, both within quite complex objects representing screens.
Other screens are represented by 100% Swing components. When a menu item is selected,
all components are removed from the JFrame’s contentpane and the proper screen is added
to it. So long story short, adding/removing GLCanvas to my swing GUI is unavoidable I think.

What if you used a CardLayout in your main frame and all of the contents were never removed from the frame. When a user clicked a menu item, just select the appropriate card, and it should look the same as what you’re doing. This should fix the GLCanvas needing removing.

Although this is a good idea and will probably solve the need of removing my GLCanvas, it is not a good option for me. Reprogramming this entire application to support the cardlayout trick will take long, trust me. It might be a good improvement for future times when we have time for such an overhaul.

Any other ideas on how I can simply draw a white background while waiting for the init() and display() to finish?

Strange, calling glClear should do the trick. Just call a swapBuffers() afterwards. See http://download.java.net/media/jogl/builds/nightly/javadoc_public/javax/media/opengl/GLDrawable.html#swapBuffers(). The javadoc in fact says you shouldn’t call this on a GLAutoDrawable, but I think it is safe to do so in your case.

the

gLAutoDrawable.swapBuffers();

did the trick.
thanks everybody for all the helpful information ;D