Workshop: Laying Out an app

The layout managers you have seen thus far were applied to an entire frame; the setLayout() method of the frame was used, and all components followed the same rules. This setup can be suitable for some programs, but as you try to develop a graphical user interface with Swing and the Abstract Windowing Toolkit, you often will find that none of the layout managers fit. One way around this problem is to use a group of JPanel objects as containers to hold different parts of a graphical user interface. You can set up different layout rules for each of these parts by using the setLayout() methods of each JPanel. Once these panels contain all of the components they need to contain, the panels can be added directly to the frame. This hour's workshop will be to develop a full interface for the program you will write during the next hour. The program is a Lotto number cruncher that will assess a user's chance of winning one of the multimillion-dollar Lotto contests in the span of a lifetime. This chance will be determined by running random six-number Lotto drawings again and again until the user's numbers turn up as a big winner. Screenshot shows the GUI you will be developing for the app.

Screenshot Displaying the graphical user interface of the LottoMadness app.

Java ScreenShot

Create a new file in your word processor called Enter Listing 14.2 and save the file when you're done.

Listing 14.2. The Full Text of
 1: import java.awt.*;
 2: import javax.swing.*;
 4: public class LottoMadness extends JFrame {
 6: // set up row 1
 7: JPanel row1 = new JPanel();
 8: ButtonGroup option = new ButtonGroup();
 9: JCheckBox quickpick = new JCheckBox("Quick Pick", false);
 10: JCheckBox personal = new JCheckBox("Personal", true);
 11: // set up row 2
 12: JPanel row2 = new JPanel();
 13: JLabel numbersLabel = new JLabel("Your picks: ", JLabel.RIGHT);
 14: JTextField[] numbers = new JTextField[6];
 15: JLabel winnersLabel = new JLabel("Winners: ", JLabel.RIGHT);
 16: JTextField[] winners = new JTextField[6];
 17: // set up row 3
 18: JPanel row3 = new JPanel();
 19: JButton stop = new JButton("Stop");
 20: JButton play = new JButton("Play");
 21: JButton reset = new JButton("Reset");
 22: // set up row 4
 23: JPanel row4 = new JPanel();
 24: JLabel got3Label = new JLabel("3 of 6: ", JLabel.RIGHT);
 25: JTextField got3 = new JTextField("0");
 26: JLabel got4Label = new JLabel("4 of 6: ", JLabel.RIGHT);
 27: JTextField got4 = new JTextField("0");
 28: JLabel got5Label = new JLabel("5 of 6: ", JLabel.RIGHT);
 29: JTextField got5 = new JTextField("0");
 30: JLabel got6Label = new JLabel("6 of 6: ", JLabel.RIGHT);
 31: JTextField got6 = new JTextField("0", 10);
 32: JLabel drawingsLabel = new JLabel("Drawings: ", JLabel.RIGHT);
 33: JTextField drawings = new JTextField("0");
 34: JLabel yearsLabel = new JLabel("Years: ", JLabel.RIGHT);
 35: JTextField years = new JTextField();
 37: public LottoMadness() {
 38: super("Lotto Madness");
 39: setSize(550, 270);
 40: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 41: GridLayout layout = new GridLayout(5, 1, 10, 10);
 42: setLayout(layout);
 44: FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER,
 45: 10, 10);
 46: option.add(quickpick);
 47: option.add(personal);
 48: row1.setLayout(layout1);
 49: row1.add(quickpick);
 50: row1.add(personal);
 51: add(row1);
 53: GridLayout layout2 = new GridLayout(2, 7, 10, 10);
 54: row2.setLayout(layout2);
 55: row2.add(numbersLabel);
 56: for (int i = 0; i < 6; i++) {
 57: numbers[i] = new JTextField();
 58: row2.add(numbers[i]);
 59: }
 60: row2.add(winnersLabel);
 61: for (int i = 0; i < 6; i++) {
 62: winners[i] = new JTextField();
 63: winners[i].setEditable(false);
 64: row2.add(winners[i]);
 65: }
 66: add(row2);
 68: FlowLayout layout3 = new FlowLayout(FlowLayout.CENTER,
 69: 10, 10);
 70: row3.setLayout(layout3);
 71: stop.setEnabled(false);
 72: row3.add(stop);
 73: row3.add(play);
 74: row3.add(reset);
 75: add(row3);
 77: GridLayout layout4 = new GridLayout(2, 3, 20, 10);
 78: row4.setLayout(layout4);
 79: row4.add(got3Label);
 80: got3.setEditable(false);
 81: row4.add(got3);
 82: row4.add(got4Label);
 83: got4.setEditable(false);
 84: row4.add(got4);
 85: row4.add(got5Label);
 86: got5.setEditable(false);
 87: row4.add(got5);
 88: row4.add(got6Label);
 89: got6.setEditable(false);
 90: row4.add(got6);
 91: row4.add(drawingsLabel);
 92: drawings.setEditable(false);
 93: row4.add(drawings);
 94: row4.add(yearsLabel);
 95: years.setEditable(false);
 96: row4.add(years);
 97: add(row4);
 99: setVisible(true);
100: }
102: public static void main(String[] arguments) {
103: LottoMadness frame = new LottoMadness();
104: }
105: }

After you compile this app, run it to see how the LottoMadness app will work. Even though you haven't added any statements that make the program do anything yet, you can make sure that the graphical interface is organized correctly and collects the information you need. This app uses several different layout managers. If you look carefully at each of the components, you might be able to determine which manager is in use in the different areas of the program. To get a clearer picture of how the app's user interface is laid out, take a look at Screenshot. The interface is divided into five horizontal rows that are separated by horizontal black lines in the figure. Each of these rows is a JPanel object, and the overall layout manager of the app organizes these rows into a GridLayout of five rows and one column.

Screenshot Dividing the LottoMadness app into panels.

Java ScreenShot

Within the rows, different layout managers are used to determine how the components should appear. Rows 1 and 3 use FlowLayout objects. Lines 44–45 of the program show how these are created:

FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER,
 10, 10);

Three arguments are used with the FlowLayout() constructor method. The first argument, FlowLayout.CENTER, indicates that the components should be centered within their container—the horizontal JPanel on which they are placed. The last two components specify the width and height that each component should be moved away from other components. Using a width of 10 pixels and a height of 10 pixels puts a small amount of extra distance between the components. Row 2 of the interface is laid out into a grid that is two rows tall and seven columns wide. The GridLayout() constructor also specifies that components should be set apart from other components by 10 pixels in each direction. Lines 53–54 set up this grid:

GridLayout layout2 = new GridLayout(2, 7, 10, 10);

Row 4 uses GridLayout to arrange components into a grid that is two rows tall and three columns wide. The LottoMadness app uses several of the components described during this hour. Lines 7–35 are used to set up objects for all of the components that make up the interface. The statements are organized by row. First, a JPanel object for the row is created, and then each component that will go on the row is set up. This code creates all of the components and containers, but they will not be displayed unless an add() method is used to add them to the app's main frame. In Lines 44–97, the components are added. Lines 44–51 are indicative of the entire LottoMadness() constructor method:

FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER,
 10, 10);

After a layout manager object is created, it is used with the setLayout() method of the row's JPanel object—row1 in this case. Once the layout has been specified, components are added to the JPanel by using its add() method. Once all of the components have been placed, the entire row1 object is added to the frame by calling its own add() method.