Animator - pause it when not in use ? ie when not interacting with the display.

I was wondering how I could limit the computer from constantly rendering my scene in JOGL when the scene is either not visible because it is in another tab of a JTabbedPane or the window is minimized, etc? Or even if the window is visible but nothing is changing in it, is there a way to prevent unnecessary repaints?

In particular, is there a way to pause the animator or temporarily disable the draw loop? Is there some setting that would allow me to run my display without taxing the resources unnecessarily?

I have the following in my code regarding the canvas that I use (using GLJPanel()) … are one of these settings incorrect? Sorry to sound like a horrible newbie, but I tried searching the forum with little luck:


        ...
        ...
        canvas.setIgnoreRepaint( true );    // canvas is a GLJPanel()

        animator = new FPSAnimator( canvas, 60, true );
        animator.setRunAsFastAsPossible(false);
        ...
        ...

It’s a thread. Try animator.wait() and when you want it to continue use animator.notify(). I didn’t use this but I suggest you to try. If that won’t work you can always stop it with stop().

I found out that my display does not use up CPU when it is minimized - which is good. It also does not use up the CPU when I switch tabs (ie the tab is not visible) - which is good too. So the main time that I am now concerned about is when the window is being displayed and there are no events occurring…ie no mouse inputs, not animations, no nothing.

I tried to use the ‘animator.wait()’ but since animator is not a thread itself but it invokes a thread I was given an exception that I am not the owner so I have no way right now to cause this wait().

I tried doing the animator.stop() and then the animator.start() on a mouse event and that seems to let me reduce the CPU usage to nothing and acts sort of like what I expect. Now I just need to write better logic for when to stop and when to start the animator…initially, as my test, I just had a separate thread running every second that would stop the animator and then I would have my animator start on a mousepressed event but of course it made the display jumpy since the stop would occur during my mouse events/rotations.

So I guess I need to essentially code it to start the animator when I do a mousepressed and stop when I’m done…and probably other logic as well…anyone do this themselves yet?

A friend came up with an interesting solution that seems to work right now in limited testing…hopefully this is not a bug that gets squashed in rc9.

Basically I created an inner class that extends FPSAnimator and that overrides the display method and calls a stop() inside that display method. This basically forces the animator to stop after every single display():…don’t mind the SarahConnor name - it is a play on Terminator/Animator. :slight_smile:


        private class SarahConnor extends FPSAnimator  {

            public SarahConnor(GLAutoDrawable drawable, int fps, boolean scheduleAtFixedRate) {
                super(drawable, fps,scheduleAtFixedRate);
            }
            
            protected void display() {
                super.display();
                stop();
                System.out.println("Sarah Connor's Display");
            }   
        } 

so now, instead of creating an instance of FPSAnimator I create a SarahConnor instance inside my main class constructor.


        //animator = new FPSAnimator( canvas, 30, true );
        animator = new SarahConnor(canvas, 30, true );

Then inside my mousehandler I have calls to my start() method for both the mouse pressed and mouse dragged events:


    public void mousePressed( MouseEvent e ) {
        thePanel.animatornotify();
    }
    public void mouseDragged( MouseEvent e ) {
        thePanel.animatornotify();
    }

and ‘thePanel’ is an instance of my Main class JPanel where I have the start() code as:


    public void start() {
        try {
            animator.start();
        } catch ( Exception e ) {
            // nothing
        }
    }

forgot to add the animatornotify code:


    public void animatornotify() {
        try {
            animator.start();
        } catch ( Exception e ) {
            System.out.println("Exception caught: " + e);
        } 
    } 

please shoot some holes at this.

Why not simply bypass the animator object completely and just simply call the renderer object’s draw method after an event occurs? It seems that starting and stopping the animator after events is a waste of time, IMHO, it seems it would be easier just to eliminate the middle man (Animator in this case)

~Bolt

i agree with Bolt.

just call the drawable’s display() function.

this might also be interesting for you:
http://www.java-gaming.org/forums/index.php?topic=18301.0

I did a post about that a cupple of monthes ago:

http://www.java-gaming.org/forums/index.php?topic=17661.0

Just to close out what I did for future reference…per boltimuss and emzic’s suggestion I instead did not create an animator instance but instead in my Mouse and Keyboard listeners I had the following code:


    public void mousePressed( MouseEvent e ) {
        thePanel.drawabledisplay();
    }
    public void mouseDragged( MouseEvent e ) {
        thePanel.drawabledisplay();
    }


    public void keyPressed( KeyEvent e ) {
        processKeyEvent(e, true);
    }

    private void processKeyEvent( KeyEvent e, boolean pressed ) {
        switch (e.getKeyCode()) {
            case KeyEvent.SOME_EVENT_HERE:
                // do something, set something
                break;

            default:
        }
        
        // Update the scene - redraw the display following a keyboard event
        thePanel.drawabledisplay();
    }

and my code in the main class (thePanel instance) where my drawable ‘canvas’ (in my case ‘canvas’ was a GLJPanel) was created has the method:


    public void drawabledisplay() {
        try {
            canvas.display();
        } catch ( Exception e ) {
            System.out.println("drawabledisplay(): Exception caught: " + e);
        } 
    }  

So this effectively does not update the display until either a mouse or key event occurs…if I had other background events I would have to make sure that they also called the ‘drawabledisplay()’ method redraw the scene.

Cool…this (and my previous method) reduce my CPU usage to 0% when nothing is changing in the scene…only when I do move around or press keys does the CPU increase. Previously I would see the CPU usage at around 50% (at least) during the entire time.

Thanks.