getting a swing application to run my simple jogl application, it goes into an infinite loop of creating windows instead of displaying graphics

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

getting a swing application to run my simple jogl application, it goes into an infinite loop of creating windows instead of displaying graphics

Steven Miller
I am writing a GUI interface in swing that calls a jogl application when I click a JButton.  I know the application works fine because I put it in a main() standalone class and it runs fine.  When I embed it in another class under a Jbutton then it doesn't.  I don't get any runtime errors, but when the program is running then it appears to opening thousands of windows and the graphics won't display.  Here is some sample code to explain what I am doing.  I have my main in a class called runGUI.  runGUI creates an object called GUI that initializes and runs the GUI.  Inside of GUI is a button that when clicked it should call my java code that is called SimpleScene (a tutorial online).

public class runGUI {
        public static void main(String[] args){
                GUI G = new GUI();
                G.pack(); /* Causes this Window to be sized to fit the preferred size and layouts of its subcomponents */
                G.setVisible(true); /* Set it to be visual */
               
        }
}
-----------------------------------------------------------------------------
public class GUI extends JFrame {

        private static final long serialVersionUID = 1L;
        private JPanel jContentPane = null;
        private JButton jButtonScan = null;
        private JDialog jButtonScanClickDialog = null;
        ExecutorService pool;
        /**
         * This is the default constructor
         */
        public GUI() {
                super();
                initialize();
        }
.......
.......
private JButton getJButtonScan() {
                if (jButtonScan == null) {
                        ImageIcon scanButtonIcon = createImageIcon("Images/GFP.jpg");
                        jButtonScan = new JButton("SCAN", scanButtonIcon);
                        jButtonScan.setVerticalTextPosition(AbstractButton.CENTER);
                jButtonScan.setHorizontalTextPosition(AbstractButton.CENTER);
                        jButtonScan.setToolTipText("This scans the sample");
                jButtonScan.setBounds(new Rectangle(8, 7, 147, 136));
                        jButtonScan.setText("SCAN");
                        jButtonScan.setForeground(Color.white);
                        jButtonScan.addActionListener(new java.awt.event.ActionListener() {
                                public void actionPerformed(java.awt.event.ActionEvent e) {
                                        System.out.println("actionPerformed()"); // TODO Auto-generated Event stub actionPerformed()
                                        pool = Executors.newCachedThreadPool();
                                        pool.execute((Runnable) new SimpleScene());
               
                                }
                        });
                       
                }
                return jButtonScan;
        }
---------------------------------------------------------------------------------------
import com.jogamp.opengl.util.*;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.awt.GLCanvas;

public class SimpleScene implements GLEventListener {
        private double theta = 0; //theta will change over time
        private double s = 0; //refer to sin of theta
        private double c = 0; //refer to cos of theta
       
    public SimpleScene() {
    GLProfile.initSingleton(false); //takes care of Linux specific locking optimization
        final GLProfile glp = GLProfile.getDefault(); //gets Glprofile so that older and newer things are compatible, kind of like the version
        final GLCapabilities caps = new GLCapabilities(glp);//This object describes some specific capabilities a rendering context should support
        final GLCanvas canvas = new GLCanvas(caps);//GLCanvas which extends the AWT Component class; creates a window/container to put things on (GLAutoDrawable)

        final Frame frame = new Frame("AWT Window Test");
        frame.setSize(300, 300);
        frame.add(canvas);
        frame.setVisible(true);
       
        // by default, an AWT Frame doesn't do anything when you click
        // the close button; this bit of code will terminate the program when
        // the window is asked to close
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(final WindowEvent e) {
                System.exit(0);
            }
        });
       
        canvas.addGLEventListener(new SimpleScene()); //Have our canvas listen for a simple scene object
        //An Animator object can be created to ensure the display method of a GLAutoDrawable is repeatedly called
        //An FPSAnimator allows us make the framerate relatively consistent and can reduce the resource consumption of the program (if it is simple enough to run faster than the target framerate)
        final FPSAnimator animator = new FPSAnimator(canvas, 60); //render at 60 frames per second
        animator.add(canvas);
        animator.start();
    }

        @Override
        public void display(GLAutoDrawable drawable) {
            update();
            render(drawable);
           // render2(drawable);
        }

        private void update() {
                //theta += 0.01;
                theta += 0.02;
                s = Math.sin(theta);
                c = Math.cos(theta);
               
        }
        /*
        private void render2(GLAutoDrawable drawable){
         GL2 gl2 = drawable.getGL().getGL2();
            gl2.glClear(GL.GL_COLOR_BUFFER_BIT);
            gl2.glBegin(GL.GL_TRIANGLES);
            gl2.glColor3f(1, 0, 0);
            gl2.glVertex2d(1, 1);
            gl2.glColor3f(0, 1, 0);
            gl2.glVertex2d(1, 2);
           
            gl2.glColor3f(0, 0, 1);
            gl2.glVertex2d(3, 2);
            gl2.glEnd();
        }
        */
       
        private void render(GLAutoDrawable drawable) {
            GL2 gl = drawable.getGL().getGL2();
            gl.glClear(GL.GL_COLOR_BUFFER_BIT);
            // draw a triangle filling the window
           
           
            int circle_points = 10000;
            gl.glBegin(GL.GL_LINE_LOOP);
            gl.glLineWidth(3f);
            for (int i = 0; i < circle_points; i++) {    
               double angle = 2*Math.PI*i/circle_points;
               gl.glVertex2d(Math.cos(angle)/2, Math.sin(angle)/2);
            }
            gl.glEnd();
           
            //changing values
            gl.glBegin(GL.GL_TRIANGLES);
                    gl.glColor3f(1, 0, 0);
                    gl.glVertex2d(-c, -c);
                    gl.glColor3f(0, 1, 0);
                    gl.glVertex2d(0, c);
                    gl.glColor3f(0, 0, 1);
                    gl.glVertex2d(s, -s);
            gl.glEnd();
           
           
           
            /*//hard coded values
            gl.glBegin(GL.GL_TRIANGLES);
            gl.glColor3f(1, 0, 0);
            gl.glVertex2f(-1, -1);
            gl.glColor3f(0, 1, 0);
            gl.glVertex2f(0, 1);
            gl.glColor3f(0, 0, 1);
            gl.glVertex2f(1, -1);
            gl.glEnd();
            */
        }

        @Override
        public void dispose(GLAutoDrawable arg0) {
                // TODO Auto-generated method stub
                //remember that resources on the graphics card, such as textures, shaders, or vertex buffer objects
        }

        @Override
        public void init(GLAutoDrawable arg0) {
                // TODO Auto-generated method stub
                /*
                 * You can, however, limit the framerate of a regular Animator by asking the graphics driver
                 * to synchronize with the refresh rate of the display (v-sync). Because the target framerate is
                 * often the same as the refresh rate, which is often 60-75 or so, this method is a great choice
                 *  as it lets the driver do the work of limiting frame changes. However, some Intel GPUs may
                 *  ignore this setting. In the init method, active v-sync as follows:
                 *
                 */
                //drawable.getGL().setSwapInterval(1);
               
                /*
                 *Then, in the main method, replace the FPSAnimator with a regular Animator:
                Animator animator = new Animator(canvas);
                 */
        }

        @Override
        public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3,
                        int arg4) {
                // TODO Auto-generated method stub
               
        }
}
-----------------------------------------------------------------------------------------------------
Can anyone help me out or tell me what is wrong?
Reply | Threaded
Open this post in threaded view
|

Re: getting a swing application to run my simple jogl application, it goes into an infinite loop of creating windows instead of displaying graphics

Wade Walker
Administrator
I'd try putting a breakpoint in the SimpleScene constructor to see why you get multiple windows

I'd also put GLProfile.initSingleton(false) in a static code block -- where it is now it won't have the desired effect.
Reply | Threaded
Open this post in threaded view
|

Re: getting a swing application to run my simple jogl application, it goes into an infinite loop of creating windows instead of displaying graphics

Justin
The constructor of SimpleScene creates a new SimpleScene ands adds it to the canvas... which then calls then constructor of SimpleScene. You can see where this is going :)
Reply | Threaded
Open this post in threaded view
|

Re: getting a swing application to run my simple jogl application, it goes into an infinite loop of creating windows instead of displaying graphics

Steven Miller
In reply to this post by Steven Miller
Thanks for the responses guys. I'll do that Wade Walker
To elaborate then Justin mentioned the following:

>The constructor of SimpleScene creates a new SimpleScene ands adds it to the canvas... which then calls the
> constructor of SimpleScene. You can see where this is going :)

I can see where this is going now that you pointed this out.  The code used to have a main function in place of where the constructor is now.  Where would be the best place or way to do this so that I can have a standalone class and initiate objects from this class, but not repeatedly call it over and over?  I am a little new to jogl and am learning a little at a time so some I would appreciate suggestions and help.  Would it make sense to put the canvas in the GUI class and call it from the GUI?  How would this work with the current threading framework?  
Reply | Threaded
Open this post in threaded view
|

Re: getting a swing application to run my simple jogl application, it goes into an infinite loop of creating windows instead of displaying graphics

Wade Walker
Administrator
As Justin pointed out, the problem is your code looks like this:

public SimpleScene() {
    ...
    canvas.addGLEventListener(new SimpleScene());
    ...
}

This is a recursive function call, probably not what you intended  If you do this instead, it uses the existing SimpleScene instead of creating a new one:

public SimpleScene() {
    ...
    canvas.addGLEventListener(this);
    ...
}

This is why I always suggest stepping through the code in a debugger -- often you can spot the problem in just a few moments, and save yourself the pain of editing and posting your code and hoping for people to reply
Reply | Threaded
Open this post in threaded view
|

Re: getting a swing application to run my simple jogl application, it goes into an infinite loop of creating windows instead of displaying graphics

Steven Miller
Thanks Wade Walker! :)  It works now.