0

I'm making my first Applet. I have a JPanel which creates a Swing GUI and performs CPU intensive tasks (repainting a Component 60Hz). My Applet displays this JPanel on event dispatching thread. here is an abstraction of the problem. Normally I would launch the applet from an html document instead of having a main method. This program puts about a 40% load on my CPU.

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;

public class TestApplet extends JApplet {
    TestPanel tp;
    public void init() {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    createGUI();
                }
            });
        } catch (Exception e) { 
            System.err.println("createGUI didn't complete successfully");
        }
    }
    private void createGUI() {
        //Create and set up the content pane.
        tp = new TestPanel();
        tp.setOpaque(true); 
        setContentPane(tp);        
    }

    public static void main(String[] args) {
        JFrame f = new JFrame("Fish Tank");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JApplet ap = new TestApplet();
        ap.init();
        f.add("Center", ap);
        f.pack();
        f.setVisible(true);
    }
}

class TestPanel extends JPanel{
    public TestTank tt = new TestTank();
    public TestPanel() {add(tt);}
    public void stop() {tt.stop();}
    public void start() {tt.start();}
}

class TestTank extends Component implements ActionListener{
    private javax.swing.Timer timer;
    TestTank(){
        timer = new javax.swing.Timer(17, this);
        timer.setCoalesce(true);
        timer.start();
    }
    public Dimension getPreferredSize(){
        return new Dimension(900, 700);
    }
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        Dimension size = getSize();
        g2.setPaint(new GradientPaint(0,0,Color.RED,900, 0,Color.WHITE));
        g2.fill(new Rectangle2D.Float(0,0,size.width,size.height));
    }
    public void actionPerformed(ActionEvent e) {
        repaint();
    }
    public void stop(){timer.stop();}
    public void start(){timer.start();}
}

My question: How do I suspend and resume execution of the JPanel (FishTankPanel) when the user switches tabs or minimizes the browser? I want the Applet to stop using the CPU when the user can't see what it is doing. I need to capture browser events in order to execute tp.stop() in the applet. I have tried to execute them with window event listeners in the JPanel, and by overriding the start() and stop() methods in the Applet. I have been unsuccessful. Any suggestions or solutions would be appreciated.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
laertiades
  • 1,992
  • 2
  • 19
  • 26
  • 2
    `stop()` is called by the browser or applet viewer to inform this applet that it should stop its execution. It is called when the Web page that contains this applet has been replaced by another page, and also just before the applet is to be destroyed. with that said please post an [SSCCE](http://sscce.org/) - which is short and compilable. – David Kroukamp Dec 23 '12 at 19:11
  • @DavidKroukamp: should your comment be an answer? – Hovercraft Full Of Eels Dec 23 '12 at 20:13
  • While your intentions are honorable, you probably should assume that if the user leaves the tab/window open, they want the applet to run. Perhaps you could put a "Suspend" button in the UI so the user can decide when their CPU is being overwhelmed. – VGR Dec 23 '12 at 20:13
  • @HovercraftFullOfEels I didn't put it as one because it doesn't really solve the problem, rather just guides the OP that `stop()` will be of no use for this situation. On that I'm not sure why the OP wants to take over the users job, as they should pause the application should they not want it to continue in the background. – David Kroukamp Dec 23 '12 at 20:27
  • I appreciate the responses. I will post an sscce. Let me mention that the applet is a virtual fishtank, the animation taxes the CPU, and there would be no reason to have it processing when it is not displayed. My feeling is that many users don't understand these things and I would like to make the applet take care of such matters as much as possible. Some help would be most welcome. I will go to work on the sscce in hopes that it will shed some light. Thanks again. – laertiades Dec 23 '12 at 21:31
  • @DavidKroukamp -- I editted my question to include an sscce. Thank you for your efforts on my behalf so far. Any further suggestions would be greatly appreciated. – laertiades Dec 23 '12 at 22:37

3 Answers3

2

I would do as Dave said and use the JApplet override start and stop methods to call your GUI methods. For instance, see changes in code:

public class TestApplet extends JApplet {
   TestPanel tp;

   public void init() {
      // ... no change
   }

   private void createGUI() {
      // ... no change
   }

   @Override
   public void stop() {
      if (tp != null) {
         tp.stop();
      }
   }

   @Override
   public void start() {
      if (tp != null) {
         tp.start();
      }
   }

}    

class TestTank extends Component implements ActionListener {
   private javax.swing.Timer timer;

   // ... no change

   public void stop() {
      timer.stop();
      System.out.println("stop");
   }

   public void start() {
      timer.start();
      System.out.println("start");
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thank you Hovercraft. I added the changes you suggested but they are not working for me. By the way, where does "System.out.println" go when the applet is running in a browser? Thanks for your help. – laertiades Dec 23 '12 at 23:17
  • 1
    It goes to the Java Console (normally available from the system tray in Windows (might need to customise the notification area)). – Philip Whitehouse Dec 23 '12 at 23:52
2

It seems you might need to leverage some JS for this. E.G. use the JS shown in this answer to explicitly call the applet start() & stop() methods on focus & blur detection respectively.

Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Thank you Andrew Thompson. Your suggestion works but it also does more than I want: It can stop the animation when the tab is still visible but another application besides the browser has focus. I feel I am on the right track, though, and I thank you – laertiades Dec 24 '12 at 20:04
0

The solution for my problem was to use javascript to implement the Page Visibility API. I then called the appropriate Java methods from within the javascript script.

laertiades
  • 1,992
  • 2
  • 19
  • 26