I currently have a small Java program which I would like to run both on the desktop (ie in a JFrame) and in an applet. Currently all of the drawing and logic are handled by a class extending Canvas. This gives me a very nice main method for the Desktop application:
public static void main(String[] args) {
MyCanvas canvas = new MyCanvas();
JFrame frame = MyCanvas.frameCanvas(canvas);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
canvas.loop();
}
Can I do something similar for the applet? Ideally MyCanvas would remain the same for both cases.
Not sure if its important but I am drawing using BufferStrategy with setIgnoreRepaint(true)
.
Edit: To clarify, my issue seems to be painting the canvas -- since all the painting is being done from the canvas.loop()
call.
Applet is a Container, just add your Canvas there.
Generally, the way you would have an application that is also an applet is to have your entry point class extend Applet, and have its setup add the Canvas to itself, etc. etc.
Then, in the main method version, you just instantiate your Applet class and add it to a new Frame (or JApplet / JFrame, etc.).
See here and here for examples of the technique, which essentially boils down to (from the first example):
public static void main(String args[])
{
Applet applet = new AppletApplication();
Frame frame = new Frame();
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
frame.add(applet);
frame.setSize(IDEAL_WIDTH,IDEAL_HEIGHT);
frame.show();
}
Canvas
is inappropriate for adding to Swing components. Use JComponent
instead (and setOpaque(true)
).
Swing components should always be manipulated on the AWT Event Dispatch Thread (EDT). Use java.awt.EventQueue.invokeLater
(invokeAndWait
for applets). You shouldn't do any blocking operations from the EDT, so start your own threads for that. By default you are running in the main thread (or applet thread for applets), which is quite separate from the EDT.
I suggest removing any dependence from your MyCanvas
to JFrame
. I also suggest keeping code for applications using frame separate from that using applets. Adding a component to a JApplet
is the same as for JFrame
(in both cases there is shenanigans where actually what happens is that add
actually calls getContentPane().add
which can cause some unnecessary confusion). The main difference is that you can't pack
an applet.