Commentary - Build window in main()

Subclassing JFrame

The most common way to build a graphical user interface is to subclass JFrame. If you haven't already, read GUI 7 - DogYears - Listeners for an example of this. Below you'll find the DogYears program rewritten in a style that builds the window entirely in main().

Writing a GUI in main()

You may sometimes see a GUI constructed entirely in the main() method.

Scaling problems. Why is it that writing the GUI in main() is less common, except for simple programs? I've never tried it for larger programs, but it doesn't seem to be appropriate as programs get larger. As the amount of code increases, it's common to write private utility methods that help you manage the user interface, for example, clearInputFields(), disableEditingControls(), etc. If you build the window in main() and store the components in final local variables, no other method can reference them. You could pass them as parameters, but things are starting to get uglier. I don't see a clean way around this, but perhaps there is one.

Anonymous inner classes

Anonymous inner classes are very useful, altho they have a somewhat cryptic syntax.

One use. They are often used when only one reference to class is needed, in which case they are defined at the point the reference is needed. In the example below, an anonymous class is created for the button action listener, in the addActionListener() call.

Inside methods. Unlike other inner classes, they can be created inside of a method, at the point an object reference is needed.

Interface name. Following the new keyword, you can write an interface name, followed by "()". This creates an anonymous class that implements that interface.

No constructor. Note that no constructor is possible (there's no name).

Final method variables/parameters. Like other inner classes, an anonymous inner class method can refer to static class variables in the enclosing class. It can also refer to final variables in the enclosing method, but not to either other local variables in the method or to any of the instance variables in the class.

Requires anonymous inner listeners and final local variables

You'll see in the example below how the JFrame subclass style was transformed into the all-in-main style by making an anonymous inner class listener and changing instance variables to final local variables.

Source code: DogYears entirely in main()

DogYears user interface

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
// File   : gui-tutorial/DogYears2main.java
// Purpose: Dog years conversion program with anonymous listener.
//          This builds the GUI entirely in main, with final 
//          local vars and anon innner class listener.
// Author : Fred Swartz - 2006-11-09

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;  // Needed for ActionListener

///////////////////////////////////////////////// class DogYears2main
class DogYears2main {
    //===================================================== constants
    private static final int DOG_YEARS_PER_HUMAN_YEAR = 7;

    public static void main(String[] args) {  //Note 1
    //======================================= final variables
        final JTextField humanYearsTF = new JTextField(3);
        final JTextField dogYearsTF   = new JTextField(3);

         // 1... Create/initialize components
        JButton convertBtn = new JButton("Convert");
        convertBtn.addActionListener(new ActionListener() {  //Note 2
            public void actionPerformed(ActionEvent e) {
                //... Get the value from the dog years textfield.
                String dyStr = dogYearsTF.getText();
                int dogYears = Integer.parseInt(dyStr);

                //... Convert it - each dog year is worth 7 human years.
                int humanYears = dogYears * DOG_YEARS_PER_HUMAN_YEAR;

                //... Convert to string and set human yrs textfield
                humanYearsTF.setText("" + humanYears);
            }
        });

        // 2... Create content panel, set layout
        JPanel content = new JPanel();
        content.setLayout(new FlowLayout());

        // 3... Add the components to the content panel.
        content.add(new JLabel("Dog Years"));
        content.add(dogYearsTF);             // Add input field
        content.add(convertBtn);               // Add button
        content.add(new JLabel("Human Years"));
        content.add(humanYearsTF);           // Add output field

        // 4... Create window and display it.
        JFrame window = new JFrame("Dog Year Converter");
        window.setContentPane(content);
        window.pack();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setLocationRelativeTo(null);  // Center window.
        window.setVisible(true);
    }
}

Notes

  1. The GUI can be built inside main by using "final" instead of instance variables, and anonymous inner class listeners. But subclassing JFrame is a more common style, .
  2. "Anonymous inner class" listeners are a common way to attach listeners to GUI components. They are used in many styles pf GUI implemenation