« Beyond the about page | Main | What ? Adobe Flash for iPhone OS is an open platform ? »

You should almost never extend JFrame in Java Swing

JFrame is one of the heaviest objects in Java Swing (JFC). Just because you extend JApplet this does not automatically mean that your should extend JFrame as well. Because do you see any start, stop or getParameter methods in JFrame ? No, because it is a window frame and not a browser plug-in. Your code should extend JPanel, JComponent and Canvas. Because then you can use the component inside a JFrame, JWindow and JApplet.

So stop creating example code that extends JFrame. This is terrible advice and is mostly a result of developers who want to ignore the event dispatch thread. Because Swing object creation must be done on the EDT but Sun sort of forgot to tell people about it. If you do not believe me then try running Substance 5 in an applet. The JApplet.createRootPane method is on the wrong thread. The fix is to extend the createRootPane method and call super.createRootPane inside a EventQueue.invokeAndWait (click "Extreme mode"). So even Sun developers themselves do not fully understand the EDT. There is a lot of legacy API nonsense clouding the issue.

Personally I use two patterns to start a Swing application. The Application pattern and the Component View pattern. Set the LAF using swing.defaultlaf or a preceding UIManager.setLookAndFeel call wrapped in EventQueue.invokeAndWait. The Component View pattern is for main based test methods in components while the Application pattern is for large monolithic structures.

PS
Right click on the media player and add http://app.teppefall.com/t.flv.


package arbeid;
import java.awt.*;
import javax.swing.*;

class Application {
JFrame mainFrame;
String args[];
String title = "Undefined";
void create() {
mainFrame = new JFrame(title);
View.configureNormalFrame(mainFrame);
}
void start() throws Exception {
if(EventQueue.isDispatchThread())
create();
else
EventQueue.invokeAndWait(new Runnable() {
public void run() {
create();
}
});
mainFrame.setVisible(true);
}
static void launch(String title, String args[], Application app) throws Exception {
app.title = title;
app.args = args;
app.start();
}
}
class View {
static void configureNormalFrame(JFrame frame) {
frame.setSize(600, 300);
frame.setLocation(100, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static JFrame asApplication(String title, JComponent panel) {
JFrame mainFrame = new JFrame(title);
configureNormalFrame(mainFrame);
mainFrame.getContentPane().add(panel);
mainFrame.setVisible(true);
return mainFrame;
}
}
class SampleComponent extends JLabel {
public SampleComponent(String text) {
super(text);
setOpaque(true);
setForeground(Color.RED);
}
public static void main(String[] args) {
View.asApplication(SampleComponent.class.getName(), new SampleComponent("Hallo View"));
}
}
public class SwingDemo {
public static void main(String[] args) throws Exception {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
SampleComponent.main(new String[] {});
}
});
Application.launch(Application.class.getName(), args, new Application() {
void create() {
super.create();
mainFrame.getContentPane().add(new SampleComponent("Hello world from App - " + args.length));
}
});
}
}

Check out Jan Erik Paulsen on Twitter.