Extends Jframe Vs. Creating It Inside the Program

Extends JFrame vs. creating it inside the program

Thoughts:

  • Avoid extending JFrame as it ties your GUI to being, well a JFrame. If instead you concentrate on creating JPanels instead, then you have the freedom to use these JPanels anywhere needed -- in a JFrame, or JDialog, or JApplet, or inside of another JPanel, or swapped with other JPanels via a CardLayout.
  • Avoid inheritance in general, especially of complex classes. This will prevent pernicious errors, such as inadvertent method overrides (try creating a JFrame or JPanel that has a getX() and getY() method to see what I mean!).
  • Avoid inheritance of complex classes if you are using an IDE: If you override a complex class, when you call methods on objects of these classes, you will have many, too many, choices of methods offered to you.
  • Encapsulation is good, is and allows for creation of safer code. Expose only that which needs to be exposed, and control that exposure as much as possible.

Why do we need to extend JFrame in a swing application?

You don't need to extend JFrame and in fact many of us who do a lot of Swing programming make it a point not to extend this class. Myself, I try to extend classes where I plan on altering the innate behavior of the class -- i.e., override one of the non-static methods of the class. Since I rarely have to do this for a JFrame, I'll rarely want to extend it.

Another reason to avoid extending it: what if you later want to display the GUI you've just created in a JDialog or a JOptionPane or in another container as part of a complex GUI? If your class extends JFrame this will be hard to do. Myself, I try to gear my GUI classes towards creating JPanels so that this is much easier to do.

A silly example based on your code:

import javax.swing.*;

// this guy extends *nothing*
public class TunaExample {
private static final int COLS = 10;
private JPanel mainPanel = new JPanel(); // this is what I'll add to contentPane
private JTextField field1 = new JTextField(COLS);
private JTextField field2 = new JTextField(COLS);
private JPasswordField passwordField = new JPasswordField(COLS);
private JComponent[] allComponents = { new JLabel("Field 1:"), field1,
new JLabel("Field 2:"), field2, new JLabel("Password:"), passwordField };

public TunaExample() {
field2.setEditable(false);
field2.setFocusable(false);
field1.setText("Field 1");
field2.setText("Uneditable");

for (JComponent comp : allComponents) {
mainPanel.add(comp);
}
}

public JComponent getMainComponent() {
return mainPanel;
}

private static void createAndShowGui() {
TunaExample tunaExample = new TunaExample();

// creating my JFrame only when I need it and where I need it
JFrame frame = new JFrame("Tuna Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(tunaExample.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Why shouldn't you extend JFrame and other components?

Generally speaking, extending the component tends to be done strictly to use the component. This severely limits your options in unnecessary ways in terms of design, so that your classes can't extend different classes, you can't hide the JFrame's methods causing it to be more difficult to maintain and easier to trigger unexpected bugs when using the class.

Typically the intention is strictly to use the class to draw a frame, and composition is preferred over inheritance.

That being said, subclassing should be fine when you intend your subclass to add project-specific functionality to the Frame (such as convenience methods and the like) where the subclass would be used instead of the Frame itself, but used as a frame in general, not as a view of a specific frame in the application.

How do I reference the JFrame when the class extends JFrame

I'm not exactly sure what you mean by the name of the JFrame. If you just want to pass a reference to your apps JFrame somewhere then well if you extend JFrame your FrameClass class is the JFrame. In this case /this/ is the right "name".

Should the first JFrame be created with 'invokeLater' or can it be created directly from main?

I have run into simple Swing applications that fail outright if not started on the Swing event thread, this happened first for me when setting look and feel. Also correct running is not guaranteed in any situation unless the GUI is started on the Swing event thread, and so for general Swing advice, I recommend

  • Always try to start your GUI on the Swing event thread.
  • Avoid extending JFrame as it's almost never needed, and limits your code.
  • Do extend JPanel if your GUI does graphics, especially if it does animation
  • Or if you want to have more control over setting the size of your GUI, and override getPreferredSize() for this.

You can paint yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding. You also never will want to draw directly in a JFrame as this risks mis-drawing one of its critical components but do often draw in JPanels, especially if doing animation, and for this you will need to extend JPanel.

Extending a JFrame

You should not extend a class, unless you want to actually extend its functionality, in the example you've shown, you should use option 2, as option 1 is an abuse of the extending feature.

In other words - as long as the answer to the question is Test a JFrame? is NO, it should not extend JFrame.



Related Topics



Leave a reply



Submit