32

When making an application using Swing, I've seen people do one of the two things to create a JFrame. Which is a better approach and why?

I'm a beginner at Java and programming. My only source of learning is books, YouTube and Stack Overflow.

import {imports};

public class GuiApp1 {

    public static void main(String[] args) {

        new GuiApp1();
    }

    public GuiApp1()  {
        JFrame guiFrame = new JFrame();

        guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        guiFrame.setTitle("Example GUI");
        guiFrame.setSize(300,250);
        ................
    }

AND

import {imports};

public class GuiApp1 extends JFrame {

    public Execute() {
        getContentPane().setBackground(Color.WHITE);
        getContentPane().setLayout(null);
        setSize(800, 600);
        .............
    }

    public static void main(String[] args) {
        Execute frame1 = new Execute();
        frame1.setVisible(true);

    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
satnam
  • 1,457
  • 4
  • 23
  • 43
  • This is just my personally opinion, many of the answer you have basically say the same thing, more or less, with occasional differing arguments but for the same point. You're going to have a hard time choosing an acceptable answer. If you choose in favour of option 1 (and you will make lots of friends if you do) I'd encourage you to have a serious look at HovercraftFullOfEels answer, as it presents the major points in a well formed answer (as opposed to my 2 cent rant ;)) – MadProgrammer Feb 25 '14 at 03:25
  • Both are wrong in one aspect: Swing components should not be created on the main Thread, only the AWT-EventQueue-0 thread. Use SwingUtilities or EventQueue.invokeLater to run code in that thread. – masterxilo Aug 20 '23 at 00:57

6 Answers6

32

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.
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 2
    *"such as inadvertent method overrides"* I like to throw in an experimental `@Overrides` for those cases. See the compiler error, all OK. Remove the notation and continue (till the time I change the method name, signature etc. then ..go to step 1, rinse and repeat). – Andrew Thompson Feb 25 '14 at 07:52
  • JFrame is involved in some memory leaks on some platforms, so if you extend it and include large objects in your sub-class then these objects will never be recovered by garbage collection. See https://stackoverflow.com/questions/39437481/jframe-is-never-garbage-collected So this isn't a style concern... but it is a practical concern. – Jason Aug 09 '17 at 17:31
18

Prefer composition over inheritance.

The 2nd example uses inheritance, but for no good reason, since it does not change the functionality of JFrame.


As an aside, if those are examples of code you are seeing, find a new source1 supplementary. Even in the few code lines shown, each does highly questionable things. E.G.

  1. Neither GUI is created on the Event Dispatch Thread.
  2. getContentPane().setBackground(Color.WHITE); getContentPane().setLayout(null); setSize(800, 600);
    • The first part of the 1st line (getContentPane()) has not been necessary since Java 1.5
    • The second line uses a null layout, which will break in more ways I can count or describe.
    • The third line should best be replaced with pack();
  3. JFrame guiFrame = new JFrame(); guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guiFrame.setTitle("Example GUI"); guiFrame.setSize(300,250);
    • The first and 3rd lines could be contracted to:
      JFrame guiFrame = new JFrame("Example GUI");
    • The 2nd line is better set to guiFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    • The 3rd line again sets a size to the frame.

Supplement

  1. Having mentioned you do search SO, here is a tip. Check out the posts of the top 15 providers of answers in the Swing top users. Whatever advice/code you glean from these people, would commit few if any of the mistakes in those code samples.

    Some don't often (or ever) provide self contained examples like a few of us commonly do (and don't look to those examples necessarily for OO design as opposed to just technique), but whatever code they provide, or advice they give, should be highly considered.
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
10

Personally, the first approach (creating an instance of JFrame) is preferred, I prefer this because...

It doesn't lock your application into a dedicated container...you see a lot of people wanting to add applets to frames and frames to applets, if they had simple put the majority of there GUI in a JPanel to start with, they wouldn't have these issues.

It also means that the UI you create is much more flexible. For example, you can re-use it, either in the current application or future applications, you don't lock yourself in.

The main gripe I have with extending JFrame is, you're not actually adding any new features or functionality to it, which could be effectively re-used beyond using setVisible

The other issue I have with extending JFrame is people then promptly override paint, which is really, really bad. There are so many issues with doing this it's simply painful to have to repeatedly list them...

So...for more 2 cents worth. Create an instance of JFrame and add your content to it. If required, create a static method call showMyAwesomeGUI which does it for you...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
8

The first approach is better.

Typically you are not adding any new functionality to the frame so creating a direct instance of the class makes sense.

Reimeus
  • 158,255
  • 15
  • 216
  • 276
2

Go for the first approach.

Because with that you can have more frames to be created. Because the application can have more than one window. As in the second case you can't create more frames.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ravi.patel
  • 119
  • 4
-4

It does not matter.

There are reasons why you might do one or the other, but absent any of those reasons it makes no difference whatsoever.

Now, if you were writing something that might operate from the command line or might be a GUI program, obviously you could want a 'main' class that was not a GUI class.

If you worked in a programming shop where one or the other was the standard, by all means follow the standard. There is no right answer to this one, and in fact very little to choose between them.

arcy
  • 12,845
  • 12
  • 58
  • 103
  • "There are reasons why you might do one or the other"...Can you give a short example of one such reason? – satnam Feb 25 '14 at 03:16
  • I did. Read it again. – arcy Feb 25 '14 at 03:19
  • 5
    *"It does not matter"* - But it does, the choice of approach will have ramifications that need to be accessed and decided on... – MadProgrammer Feb 25 '14 at 03:21
  • Of course the choice has ramifications, but none of them make one preferable over the other. If there's a fork in the road, and both roads end up in the same place, it may not matter which one you take, but they will be different. – arcy Feb 25 '14 at 03:23
  • 1
    *"it may not matter which one you take"* And it also might if the bridge is out on road 1. The devil is in the details. – Andrew Thompson Feb 25 '14 at 03:37