Using JOGL in AWT SWT and Swing: Difference between revisions

From JogampWiki
Jump to navigation Jump to search
m (windowing -> window)
(Changed javax.media to com.jogamp)
 
(15 intermediate revisions by 2 users not shown)
Line 10: Line 10:


<pre>
<pre>
import javax.media.opengl.GL;
import com.jogamp.opengl.GL;
import javax.media.opengl.GL2;
import com.jogamp.opengl.GL2;
import javax.media.opengl.glu.GLU;
import com.jogamp.opengl.glu.GLU;


public class OneTriangle {
public class OneTriangle {
Line 51: Line 51:


<pre>
<pre>
import javax.media.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import com.jogamp.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilities;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.awt.GLCanvas;


import java.awt.Frame;
import java.awt.Frame;
Line 67: Line 67:
  */
  */
public class OneTriangleAWT {
public class OneTriangleAWT {
    static {
        // setting this true causes window events not to get sent on Linux if you run from inside Eclipse
        GLProfile.initSingleton( false );
    }


     public static void main( String [] args ) {
     public static void main( String [] args ) {
Line 95: Line 90:
             @Override
             @Override
             public void display( GLAutoDrawable glautodrawable ) {
             public void display( GLAutoDrawable glautodrawable ) {
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getWidth(), glautodrawable.getHeight() );
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
             }
             }
         });
         });
Line 117: Line 112:
= JOGL in SWT =
= JOGL in SWT =


The [http://www.eclipse.org/swt/ Standard Widget Toolkit (SWT)] is a thin layer over each platform's native window toolkit. SWT is the toolkit used in Eclipse, so it makes sense to use SWT in Eclipse-based applications. Here's how to use it.
The [http://www.eclipse.org/swt/ Standard Widget Toolkit (SWT)] is a thin layer over each platform's native window toolkit. SWT is the toolkit used in Eclipse, so it makes sense to use SWT in Eclipse-based applications. To compile this, you'll need the swt.jar file for your platform which you can get [http://www.eclipse.org/swt/ here].
 
When running this code on Mac OS X, you'll need to give the <tt>-XstartOnFirstThread</tt> argument to the JVM. This insures that the SWT windowing code sends and recieves messages on thread 0, which is required by Cocoa.


<pre>
<pre>
Line 133: Line 130:
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Shell;


import javax.media.opengl.GLProfile;
import com.jogamp.opengl.GLProfile;
import javax.media.opengl.GLContext;
import com.jogamp.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLDrawableFactory;


/**
/**
Line 143: Line 140:
  */
  */
public class OneTriangleSWT {
public class OneTriangleSWT {
    static {
        // setting this true causes window events not to get sent on Linux if you run from inside Eclipse
        GLProfile.initSingleton( false );
    }


     public static void main( String [] args ) {
     public static void main( String [] args ) {
Line 206: Line 198:
= JOGL in SWT using the SWT-AWT bridge =
= JOGL in SWT using the SWT-AWT bridge =


The SWT-AWT bridge was created to allow SWT applications to use the AWT GLCanvas. You should use this if you have problems with the SWT GLCanvas. Here's how to do it.
The SWT-AWT bridge was created to allow SWT applications to use the AWT GLCanvas. You should use this if you have problems with the SWT GLCanvas. For example, the SWT GLCanvas doesn't currently support multisampling on Windows (see [https://bugs.eclipse.org/bugs/show_bug.cgi?id=136514 here] and [http://jogamp.762907.n3.nabble.com/New-tutorial-on-AWT-SWT-Swing-GLJPanel-GLCanvas-tp2363921p2366724.html here] for details).
 
As with normal SWT, to compile this you'll need the swt.jar file for your platform which you can get [http://www.eclipse.org/swt/ here]. And just as with normal SWT, when running this code on Mac OS X, you'll need to give the <tt>-XstartOnFirstThread</tt> argument to the JVM.


<pre>
<pre>
Line 218: Line 212:
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Shell;


import javax.media.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import com.jogamp.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.awt.GLCanvas;


/**
/**
Line 231: Line 225:
  */
  */
public class OneTriangleSWTAWTBridge {
public class OneTriangleSWTAWTBridge {
    static {
        GLProfile.initSingleton( false );
    }


     public static void main( String [] args ) {
     public static void main( String [] args ) {
Line 269: Line 259:
             @Override
             @Override
             public void display( GLAutoDrawable glautodrawable ) {
             public void display( GLAutoDrawable glautodrawable ) {
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getWidth(), glautodrawable.getHeight() );
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
             }
             }
         });
         });
Line 290: Line 280:


<pre>
<pre>
import javax.media.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import com.jogamp.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilities;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.awt.GLCanvas;
import javax.swing.JFrame;
import javax.swing.JFrame;


Line 307: Line 297:
  */
  */
public class OneTriangleSwingGLCanvas {
public class OneTriangleSwingGLCanvas {
    static {
        // setting this true causes window events not to get sent on Linux if you run from inside Eclipse
        GLProfile.initSingleton( false );
    }


     public static void main( String [] args ) {
     public static void main( String [] args ) {
Line 335: Line 320:
             @Override
             @Override
             public void display( GLAutoDrawable glautodrawable ) {
             public void display( GLAutoDrawable glautodrawable ) {
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getWidth(), glautodrawable.getHeight() );
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
             }
             }
         });
         });
Line 356: Line 341:
= JOGL in Swing using the GLJPanel =
= JOGL in Swing using the GLJPanel =


In cases where the AWT GLCanvas has problems integrating with Swing components correctly, the GLJPanel can be used instead. It's supposed integrate 100% correctly into Swing, but with lower performance. Here's how to do it.
In cases where the AWT GLCanvas has problems integrating with Swing components correctly, you can use the GLJPanel instead. For example, JInternalFrames behave incorrectly when used with a GLCanvas -- you have to add JInternalFrames to the Frame that holds the GLCanvas, and when you drag the JInternalFrames around, the GLCanvas doesn't redraw properly underneath it.
 
In contrast, GLJPanel is supposed integrate 100% correctly into Swing, but with lower performance due to extra copying of the frame buffer. Here's how to do it.


<pre>
<pre>
import javax.media.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import com.jogamp.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import com.jogamp.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilities;
import javax.media.opengl.awt.GLJPanel;
import com.jogamp.opengl.awt.GLJPanel;
import javax.swing.JFrame;
import javax.swing.JFrame;


Line 376: Line 363:
  */
  */
public class OneTriangleSwingGLJPanel {
public class OneTriangleSwingGLJPanel {
    static {
        // setting this true causes window events not to get sent on Linux if you run from inside Eclipse
        GLProfile.initSingleton( false );
    }


     public static void main( String [] args ) {
     public static void main( String [] args ) {
Line 404: Line 386:
             @Override
             @Override
             public void display( GLAutoDrawable glautodrawable ) {
             public void display( GLAutoDrawable glautodrawable ) {
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getWidth(), glautodrawable.getHeight() );
                 OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
             }
             }
         });
         });

Latest revision as of 22:07, 3 July 2015

You can use JOGL with three different Java window toolkits: AWT, SWT, and Swing. This page shows examples of all three toolkits, plus variations on two of them. The example program just draws one triangle that fills a resizable window.

How to choose a window toolkit

Usually the window toolkit you use for JOGL is dictated by your application. If you're writing an Eclipse-based application, it makes sense to use SWT, since it's the native windowing system of Eclipse. Otherwise, Swing is probably the way to go. If you want to wrap native controls instead of drawing in software like Swing, and you're not writing an Eclipse app, AWT is your best choice.

Base class

First, a base class that we'll use in all five examples. This class abstracts out all the pure OpenGL calls that don't depend on the choice of window toolkit.

import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.glu.GLU;

public class OneTriangle {
    protected static void setup( GL2 gl2, int width, int height ) {
        gl2.glMatrixMode( GL2.GL_PROJECTION );
        gl2.glLoadIdentity();

        // coordinate system origin at lower left with width and height same as the window
        GLU glu = new GLU();
        glu.gluOrtho2D( 0.0f, width, 0.0f, height );

        gl2.glMatrixMode( GL2.GL_MODELVIEW );
        gl2.glLoadIdentity();

        gl2.glViewport( 0, 0, width, height );
    }

    protected static void render( GL2 gl2, int width, int height ) {
        gl2.glClear( GL.GL_COLOR_BUFFER_BIT );

        // draw a triangle filling the window
        gl2.glLoadIdentity();
        gl2.glBegin( GL.GL_TRIANGLES );
        gl2.glColor3f( 1, 0, 0 );
        gl2.glVertex2f( 0, 0 );
        gl2.glColor3f( 0, 1, 0 );
        gl2.glVertex2f( width, 0 );
        gl2.glColor3f( 0, 0, 1 );
        gl2.glVertex2f( width / 2, height );
        gl2.glEnd();
    }
}

JOGL in AWT

The Abstract Window Toolkit (AWT) was Java's first window toolkit. It's a thin layer over each platform's native window toolkit. Here's how to use JOGL in AWT.

import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.awt.GLCanvas;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
 * A minimal program that draws with JOGL in an AWT Frame.
 *
 * @author Wade Walker
 */
public class OneTriangleAWT {

    public static void main( String [] args ) {
        GLProfile glprofile = GLProfile.getDefault();
        GLCapabilities glcapabilities = new GLCapabilities( glprofile );
        final GLCanvas glcanvas = new GLCanvas( glcapabilities );

        glcanvas.addGLEventListener( new GLEventListener() {
            
            @Override
            public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
                OneTriangle.setup( glautodrawable.getGL().getGL2(), width, height );
            }
            
            @Override
            public void init( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void dispose( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void display( GLAutoDrawable glautodrawable ) {
                OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
            }
        });

        final Frame frame = new Frame( "One Triangle AWT" );
        frame.add( glcanvas );
        frame.addWindowListener( new WindowAdapter() {
            public void windowClosing( WindowEvent windowevent ) {
                frame.remove( glcanvas );
                frame.dispose();
                System.exit( 0 );
            }
        });

        frame.setSize( 640, 480 );
        frame.setVisible( true );
    }
}

JOGL in SWT

The Standard Widget Toolkit (SWT) is a thin layer over each platform's native window toolkit. SWT is the toolkit used in Eclipse, so it makes sense to use SWT in Eclipse-based applications. To compile this, you'll need the swt.jar file for your platform which you can get here.

When running this code on Mac OS X, you'll need to give the -XstartOnFirstThread argument to the JVM. This insures that the SWT windowing code sends and recieves messages on thread 0, which is required by Cocoa.

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawableFactory;

/**
 * A minimal program that draws with JOGL in an SWT Composite.
 *
 * @author Wade Walker
 */
public class OneTriangleSWT {

    public static void main( String [] args ) {
        Display display = new Display();
        final Shell shell = new Shell( display );
        shell.setText( "OneTriangle SWT" );
        shell.setLayout( new FillLayout() );
        shell.setSize( 640, 480 );

        final Composite composite = new Composite( shell, SWT.NONE );
        composite.setLayout( new FillLayout() );

        GLData gldata = new GLData();
        gldata.doubleBuffer = true;
        // need SWT.NO_BACKGROUND to prevent SWT from clearing the window
        // at the wrong times (we use glClear for this instead)
        final GLCanvas glcanvas = new GLCanvas( composite, SWT.NO_BACKGROUND, gldata );
        glcanvas.setCurrent();
        GLProfile glprofile = GLProfile.getDefault();
        final GLContext glcontext = GLDrawableFactory.getFactory( glprofile ).createExternalGLContext();

        // fix the viewport when the user resizes the window
        glcanvas.addListener( SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
                Rectangle rectangle = glcanvas.getClientArea();
                glcanvas.setCurrent();
                glcontext.makeCurrent();
                OneTriangle.setup( glcontext.getGL().getGL2(), rectangle.width, rectangle.height );
                glcontext.release();        
            }
        });

        // draw the triangle when the OS tells us that any part of the window needs drawing
        glcanvas.addPaintListener( new PaintListener() {
            public void paintControl( PaintEvent paintevent ) {
                Rectangle rectangle = glcanvas.getClientArea();
                glcanvas.setCurrent();
                glcontext.makeCurrent();
                OneTriangle.render(glcontext.getGL().getGL2(), rectangle.width, rectangle.height);
                glcanvas.swapBuffers();
                glcontext.release();        
            }
        });

        shell.open();

        while( !shell.isDisposed() ) {
            if( !display.readAndDispatch() )
                display.sleep();
        }

        glcanvas.dispose();
        display.dispose();
    }
}

JOGL in SWT using the SWT-AWT bridge

The SWT-AWT bridge was created to allow SWT applications to use the AWT GLCanvas. You should use this if you have problems with the SWT GLCanvas. For example, the SWT GLCanvas doesn't currently support multisampling on Windows (see here and here for details).

As with normal SWT, to compile this you'll need the swt.jar file for your platform which you can get here. And just as with normal SWT, when running this code on Mac OS X, you'll need to give the -XstartOnFirstThread argument to the JVM.

import java.awt.Frame;

import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;

/**
 * A minimal program that draws with JOGL in an SWT Composite using an
 * embedded AWT Frame and the AWT GLCanvas via the SWT-AWT bridge.
 *
 * @author Wade Walker
 */
public class OneTriangleSWTAWTBridge {

    public static void main( String [] args ) {
        GLProfile glprofile = GLProfile.getDefault();
        GLCapabilities glcapabilities = new GLCapabilities( glprofile );
        final GLCanvas glcanvas = new GLCanvas( glcapabilities );

        Display display = new Display();
        final Shell shell = new Shell( display );
        shell.setText( "OneTriangle SWT AWT Bridge" );
        shell.setLayout( new FillLayout() );
        shell.setSize( 640, 480 );

        final Composite composite = new Composite( shell, SWT.EMBEDDED );
        composite.setLayout( new FillLayout() );

        Frame frame = SWT_AWT.new_Frame( composite );
        frame.add( glcanvas );

        glcanvas.addGLEventListener( new GLEventListener() {
            @Override
            public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
                OneTriangle.setup( glautodrawable.getGL().getGL2(), width, height );
            }
            
            @Override
            public void init( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void dispose( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void display( GLAutoDrawable glautodrawable ) {
                OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
            }
        });

        shell.open();

        while( !shell.isDisposed() ) {
            if( !display.readAndDispatch() )
                display.sleep();
        }

        display.dispose();
    }
}

JOGL in Swing

Swing is the primary Java window toolkit since Java 1.2 in 1997. It's based on AWT at a low level, but draws all its own controls instead of wrapping native controls. Here's how to use JOGL in Swing.

import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.awt.GLCanvas;
import javax.swing.JFrame;

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
 * A minimal program that draws with JOGL in a Swing JFrame using the AWT GLCanvas.
 *
 * @author Wade Walker
 */
public class OneTriangleSwingGLCanvas {

    public static void main( String [] args ) {
        GLProfile glprofile = GLProfile.getDefault();
        GLCapabilities glcapabilities = new GLCapabilities( glprofile );
        final GLCanvas glcanvas = new GLCanvas( glcapabilities );

        glcanvas.addGLEventListener( new GLEventListener() {
            
            @Override
            public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
                OneTriangle.setup( glautodrawable.getGL().getGL2(), width, height );
            }
            
            @Override
            public void init( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void dispose( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void display( GLAutoDrawable glautodrawable ) {
                OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
            }
        });

        final JFrame jframe = new JFrame( "One Triangle Swing GLCanvas" ); 
        jframe.addWindowListener( new WindowAdapter() {
            public void windowClosing( WindowEvent windowevent ) {
                jframe.dispose();
                System.exit( 0 );
            }
        });

        jframe.getContentPane().add( glcanvas, BorderLayout.CENTER );
        jframe.setSize( 640, 480 );
        jframe.setVisible( true );
    }
}

JOGL in Swing using the GLJPanel

In cases where the AWT GLCanvas has problems integrating with Swing components correctly, you can use the GLJPanel instead. For example, JInternalFrames behave incorrectly when used with a GLCanvas -- you have to add JInternalFrames to the Frame that holds the GLCanvas, and when you drag the JInternalFrames around, the GLCanvas doesn't redraw properly underneath it.

In contrast, GLJPanel is supposed integrate 100% correctly into Swing, but with lower performance due to extra copying of the frame buffer. Here's how to do it.

import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.awt.GLJPanel;
import javax.swing.JFrame;

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
 * A minimal program that draws with JOGL in a Swing JFrame using the AWT GLJPanel.
 *
 * @author Wade Walker
 */
public class OneTriangleSwingGLJPanel {

    public static void main( String [] args ) {
        GLProfile glprofile = GLProfile.getDefault();
        GLCapabilities glcapabilities = new GLCapabilities( glprofile );
        GLJPanel gljpanel = new GLJPanel( glcapabilities ); 

        gljpanel.addGLEventListener( new GLEventListener() {
            
            @Override
            public void reshape( GLAutoDrawable glautodrawable, int x, int y, int width, int height ) {
                OneTriangle.setup( glautodrawable.getGL().getGL2(), width, height );
            }
            
            @Override
            public void init( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void dispose( GLAutoDrawable glautodrawable ) {
            }
            
            @Override
            public void display( GLAutoDrawable glautodrawable ) {
                OneTriangle.render( glautodrawable.getGL().getGL2(), glautodrawable.getSurfaceWidth(), glautodrawable.getSurfaceHeight() );
            }
        });

        final JFrame jframe = new JFrame( "One Triangle Swing GLJPanel" ); 
        jframe.addWindowListener( new WindowAdapter() {
            public void windowClosing( WindowEvent windowevent ) {
                jframe.dispose();
                System.exit( 0 );
            }
        });

        jframe.getContentPane().add( gljpanel, BorderLayout.CENTER );
        jframe.setSize( 640, 480 );
        jframe.setVisible( true );
    }
}