Summary


The Final GUI

It is beyond the capacity of a single chapter in a book to fully cover the components, and I have no intention of trying. For the most part, the javadocs (You have been using them, right?) are sufficient for describing the many properties and methods of the various components. So, this chapter will conclude by combining the learn-by-example approach with your own ability to use the javadocs to deepen your understanding.

Example 12.8 is a larger code example that creates a JFrame containing most of the JComponents listed in tables 12-9 through 12-16. JOptionPane and JColorChooser will be incorporated into the program in the next chapter when we begin to customize the application’s behavior. Except for lines 67 - 77 which make brief use of the List, Vector and Arrays class, nothing in the application is beyond the scope of this or previous chapters. You may safely ignore these lines as you read through the code or, if you would like, browse ahead to the chapter on Collections. Please read through the code, then compile and run it. Figure 12-41 shows the results of running example 12.8. Click buttons, type text into the fields, resize the window and generally experiment to get an idea of how much behavior the AWT and the Swing components provide by default. Consult tables 12-9 through 12-16 and figure 12-42 to make sure you know which component is which and what it does. Finally, study the output of the call to TreePrinterUtils.printLayout (line 100) and figure 12-43 to solidify your understanding of the application’s layout.

Example 12.8: chap12.MainFrame.java

image from book
 1     package chap12; 2 3     import java.awt.BorderLayout; 4     import java.awt.Color; 5     import java.awt.GridLayout; 6     import java.util.Arrays; 7     import java.util.List; 8     import java.util.Vector; 9 10    import javax.swing.ButtonGroup; 11    import javax.swing.JButton; 12    import javax.swing.JCheckBox; 13    import javax.swing.JComboBox; 14    import javax.swing.JFrame; 15    import javax.swing.JLabel; 16    import javax.swing.JList; 17    import javax.swing.JMenu; 18    import javax.swing.JMenuBar; 19    import javax.swing.JMenuItem; 20    import javax.swing.JPanel; 21    import javax.swing.JPasswordField; 22    import javax.swing.JRadioButton; 23    import javax.swing.JScrollPane; 24    import javax.swing.JSlider; 25    import javax.swing.JTextArea; 26    import javax.swing.JTextField; 27    import javax.swing.JToggleButton; 28    import javax.swing.border.EtchedBorder; 29    import javax.swing.border.LineBorder; 30    import javax.swing.border.TitledBorder; 31 32    import utils.TreePrinterUtils; 33 34    public class MainFrame extends JFrame { 35      protected JPanel displayOptionsPanel; 36      protected JButton bgColorButton; 37      protected JButton defaultColorButton; 38 39      protected JToggleButton lockingToggleButton; 40      protected JTextArea textArea; 41      protected JComboBox fontStyleComboBox; 42      protected JSlider fontSizeSlider; 43      protected JLabel sliderLabel; 44      protected JLabel eventLabel; 45 46      protected JList saladList; 47      protected JTextField chosenItemTextField; 48 49      protected JPasswordField secretCodeField; 50 51      protected JMenuItem menuItem1; 52      protected JMenuItem menuItem2; 53      protected JMenuItem menuItem3; 54      protected JMenuItem menuItem4; 55 56      protected JCheckBox vegetablesCheckBox; 57      protected JCheckBox fruitsCheckBox; 58      protected JCheckBox nutsCheckBox; 59      protected JCheckBox cheesesCheckox; 60 61      protected JRadioButton titleBorderRadioButton; 62      protected JRadioButton lineBorderRadioButton; 63      protected JRadioButton etchedBorderRadioButton; 64      protected JRadioButton bevelBorderRadioButton; 65      protected JRadioButton noBorderRadioButton; 66 67      protected List vegetables = 68        Arrays.asList( 69          new String[] { "Tomatoes", "Lettuce", "Cucumbers", "Olives" }); 70      protected List fruits = 71        Arrays.asList(new String[] { "Apples", "Oranges", "Dates" }); 72      protected List nuts = 73        Arrays.asList(new String[] { "Walnuts", "Almonds", "Peanuts" }); 74      protected List cheeses = 75        Arrays.asList( 76          new String[] { "Jack Cheese", "Cheddar Cheese", "Jalapeno Cheese" }); 77      protected Vector saladListItems = new Vector(vegetables); 78 79      public MainFrame() { 80        super("Introduction to Swing GUIs"); 81        JMenuBar menuBar1 = createMenuBar(); 82        setJMenuBar(menuBar1); 83 84        JPanel contentPane = new JPanel(); 85        setContentPane(contentPane); 86        contentPane.setLayout(new BorderLayout()); 87 88        JPanel centerPanel = createCenterPanel(); 89        contentPane.add(centerPanel, BorderLayout.CENTER); 90 91        JPanel northPanel = createNorthPanel(); 92        contentPane.add(northPanel, BorderLayout.NORTH); 93 94        JPanel southPanel = createSouthPanel(); 95        contentPane.add(southPanel, BorderLayout.SOUTH); 96 97        setSize(600, 600); 98        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 99        setVisible(true); 100       TreePrinterUtils.printLayout(this); 101     } 102     private JMenuBar createMenuBar() { 103       JMenuBar menuBar = new JMenuBar(); 104       JMenu menu1 = new JMenu("Menu 1"); 105       menuBar.add(menu1); 106       menuItem1 = new JMenuItem("Menu Item 1"); 107       menu1.add(menuItem1); 108       menuItem2 = new JMenuItem("Menu Item 2"); 109       menu1.add(menuItem2); 110       JMenu menu2 = new JMenu("Menu 2"); 111       menuBar.add(menu2); 112       menuItem3 = new JMenuItem("Menu Item 3"); 113       menu2.add(menuItem3); 114       menuItem4 = new JMenuItem("Menu Item 4"); 115       menu2.add(menuItem4); 116       return menuBar; 117     } 118     private JPanel createCenterPanel() { 119       JPanel centerPanel = new JPanel(new BorderLayout()); 120       JPanel centerNorthPanel = new JPanel(new GridLayout(0, 2)); 121       eventLabel = 122         new JLabel("Textarea events will display here.", JLabel.CENTER); 123       eventLabel.setBorder(new LineBorder(Color.red)); 124       eventLabel.setOpaque(true); 125       eventLabel.setBackground(Color.yellow); 126       eventLabel.setForeground(Color.red); 127       centerNorthPanel.add(eventLabel, BorderLayout.CENTER); 128       lockingToggleButton = new JToggleButton("Lock Text Area"); 129       centerNorthPanel.add(lockingToggleButton, BorderLayout.WEST); 130       centerPanel.add(centerNorthPanel, BorderLayout.NORTH); 131 132       textArea = new JTextArea(30, 60); 133       textArea.setFont(textArea.getFont().deriveFont((float)24)); 134       textArea.setLineWrap(true); 135       textArea.setWrapStyleWord(true); 136       centerPanel.add(new JScrollPane(textArea), BorderLayout.CENTER); 137       return centerPanel; 138     } 139     private JPanel createNorthPanel() { 140       JPanel northPanel = new JPanel(new BorderLayout()); 141 142       displayOptionsPanel = createDisplayOptionsPanel(); 143       northPanel.add(displayOptionsPanel, BorderLayout.WEST); 144 145       JPanel saladOptionsPanel = createSaladOptionsPanel(); 146       northPanel.add(saladOptionsPanel, BorderLayout.CENTER); 147 148       return northPanel; 149     } 150     private JPanel createDisplayOptionsPanel() { 151       displayOptionsPanel = new JPanel(); 152       displayOptionsPanel.setBorder(new TitledBorder("Panel Options")); 153 154       JPanel colorButtonPanel = new JPanel(new GridLayout(0, 1)); 155       bgColorButton = new JButton("Choose Background Color"); 156       bgColorButton.setToolTipText("Click to select background color."); 157       colorButtonPanel.add(bgColorButton); 158       defaultColorButton = new JButton("Default Background Color"); 159       defaultColorButton.setToolTipText( 160         "Click to restore background color to its default."); 161       colorButtonPanel.add(defaultColorButton); 162       displayOptionsPanel.add(colorButtonPanel); 163 164       JPanel radioPanel = new JPanel(new GridLayout(0, 1)); 165       radioPanel.setBorder(new TitledBorder("Borders")); 166 167       noBorderRadioButton = new JRadioButton("No Border"); 168       radioPanel.add(noBorderRadioButton); 169       titleBorderRadioButton = new JRadioButton("TitleBorder"); 170       titleBorderRadioButton.setSelected(true); 171       radioPanel.add(titleBorderRadioButton); 172       lineBorderRadioButton = new JRadioButton("LineBorder"); 173       radioPanel.add(lineBorderRadioButton); 174       etchedBorderRadioButton = new JRadioButton("EtchedBorder"); 175       radioPanel.add(etchedBorderRadioButton); 176       bevelBorderRadioButton = new JRadioButton("BevelBorder"); 177       radioPanel.add(bevelBorderRadioButton); 178       ButtonGroup buttonGroup = new ButtonGroup(); 179       buttonGroup.add(noBorderRadioButton); 180       buttonGroup.add(titleBorderRadioButton); 181       buttonGroup.add(lineBorderRadioButton); 182       buttonGroup.add(etchedBorderRadioButton); 183       buttonGroup.add(bevelBorderRadioButton); 184       displayOptionsPanel.add(radioPanel); 185 186       return displayOptionsPanel; 187     } 188     private JPanel createSaladOptionsPanel() { 189       JPanel saladOptionsPanel = new JPanel(new BorderLayout()); 190       saladOptionsPanel.setBorder(new TitledBorder("Salad Options")); 191 192       JPanel checkBoxPanel = new JPanel(new GridLayout(0, 1)); 193       checkBoxPanel.setBorder(new TitledBorder("Ingredients")); 194       vegetablesCheckBox = new JCheckBox("Vegetables"); 195       vegetablesCheckBox.setSelected(true); 196       checkBoxPanel.add(vegetablesCheckBox); 197       fruitsCheckBox = new JCheckBox("Fruits"); 198       checkBoxPanel.add(fruitsCheckBox); 199       nutsCheckBox = new JCheckBox("Nuts"); 200       checkBoxPanel.add(nutsCheckBox); 201       cheesesCheckBox = new JCheckBox("Cheeses"); 202       checkBoxPanel.add(cheesesCheckBox); 203       saladOptionsPanel.add(checkBoxPanel, BorderLayout.WEST); 204 205       saladList = new JList(vegetables.toArray()); 206       JScrollPane scrollPane1 = new JScrollPane(saladList); 207       saladOptionsPanel.add(scrollPane1, BorderLayout.CENTER); 208 209       chosenItemTextField = new JTextField(); 210       saladOptionsPanel.add(chosenItemTextField, BorderLayout.SOUTH); 211       return saladOptionsPanel; 212     } 213     private JPanel createSouthPanel() { 214       JPanel southPanel = new JPanel(); 215 216       JPanel fontPanel = new JPanel(new BorderLayout()); 217       fontPanel.setBorder(new TitledBorder("Font")); 218       fontStyleComboBox = 219       new JComboBox(new String[] { "Plain", "Bold", "Italic", "Bold+Italic" }); 220       fontPanel.add(fontStyleComboBox, BorderLayout.WEST); 221 222       fontSizeSlider = new JSlider(1, 200, 24); 223       fontPanel.add(fontSizeSlider, BorderLayout.CENTER); 224       sliderLabel = new JLabel(String.valueOf(fontSizeSlider.getValue())); 225       fontPanel.add(sliderLabel, BorderLayout.EAST); 226       southPanel.add(fontPanel); 227 228       JPanel codePanel = new JPanel(); 229       codePanel.setBorder(new EtchedBorder()); 230 231       codePanel.add(new JLabel("Enter Secret Code:")); 232       secretCodeField = new JPasswordField(10); 233       codePanel.add(secretCodeField); 234       southPanel.add(codePanel); 235       return southPanel; 236     } 237     public static void main(String[] arg) { 238       MainFrame frame = new MainFrame(); 239     } 240   }
image from book

image from book
Figure 12-41: MainFrame GUI

image from book
Figure 12-42: Visual Guide to the Components in MainFrame

image from book
Figure 12-43: MainFrame Layout

Use the following commands to compile and execute the example. From the directory containing the src folder:

 javac –d classes -sourcepath src src/chap12/MainFrame.java java –cp classes chap12.MainFrame

Following is the console output from running the MainFrame application.

 MainFrame [0, 0, 600, 600] (BorderLayout: 1 child) +--JRootPane [4, 24, 592, 572] (JRootPane$RootLayout: 2 children)    +--JPanel [0, 0, 592, 572]    +--JLayeredPane [0, 0, 592, 572] (null: 2 children)       +--JMenuBar [0, 0, 592, 23] (DefaultMenuLayout: 2 children)       |  +--JMenu [0, 1, 53, 21]       |  +--JMenu [53, 1, 53, 21]       +--JPanel [0, 23, 592, 549] (BorderLayout: 3 children)          +--JPanel [0, 193, 592, 295] (BorderLayout: 2 children)          |  +--JPanel [0, 0, 592, 26] (GridLayout: 2 children)          |  |  +--JLabel [0, 0, 296, 26]          |  |  +--JToggleButton [296, 0, 296, 26]          |  +--JScrollPane [0, 26, 592, 269] (ScrollPaneLayout$UIResource: 3 children)          |     +--JViewport [1, 1, 574, 266] (ViewportLayout: 1 child)          |     |  +--JTextArea [0, 0, 574, 960]          |     +--JScrollPane$ScrollBar [575, 1, 15, 266] (MetalScrollBarUI: 2 children)          |     |  +--MetalScrollButton [0, 251, 15, 15]          |     |  +--MetalScrollButton [0, 0, 15, 15]          |     +--JScrollPane$ScrollBar [0, 0, 0, 0] (MetalScrollBarUI: 2 children)          |        +--MetalScrollButton [0, 0, 0, 0]          |        +--MetalScrollButton [0, 0, 0, 0]          +--JPanel [0, 0, 592, 193] (BorderLayout: 2 children)          |  +--JPanel [0, 0, 320, 193] (FlowLayout: 2 children)          |  |  +--JPanel [10, 73, 182, 52] (GridLayout: 2 children)          |  |  |  +--JButton [0, 0, 182, 26]          |  |  |  +--JButton [0, 26, 182, 26]          |  |  +--JPanel [197, 26, 113, 146] (GridLayout: 5 children)          |  |     +--JRadioButton [5, 21, 103, 24]          |  |     +--JRadioButton [5, 45, 103, 24]          |  |     +--JRadioButton [5, 69, 103, 24]          |  |     +--JRadioButton [5, 93, 103, 24]          |  |     +--JRadioButton [5, 117, 103, 24]          |  +--JPanel [320, 0, 272, 193] (BorderLayout: 3 children)          |     +--JPanel [5, 21, 99, 147] (GridLayout: 4 children)          |     |  +--JCheckBox [5, 21, 89, 30]          |     |  +--JCheckBox [5, 51, 89, 30]          |     |  +--JCheckBox [5, 81, 89, 30]          |     |  +--JCheckBox [5, 111, 89, 30]          |     +--JScrollPane [104, 21, 163, 147] (ScrollPaneLayout$UIResource: 3 children)          |     |  +--JViewport [1, 1, 160, 144] (ViewportLayout: 1 child)          |     |  |  +--JList [0, 0, 160, 144] (null: 1 child)          |     |  |     +--CellRendererPane [0, 0, 0, 0] (null: 1 child)          |     |  |        +--DefaultListCellRenderer$UIResource [-160, -18, 0, 0]          |     |  +--JScrollPane$ScrollBar [0, 0, 0, 0] (MetalScrollBarUI: 2 children)          |     |  |  +--MetalScrollButton [0, 0, 0, 0]          |     |  |  +--MetalScrollButton [0, 0, 0, 0]          |     |  +--JScrollPane$ScrollBar [0, 0, 0, 0] (MetalScrollBarUI: 2 children)          |     |     +--MetalScrollButton [0, 0, 0, 0]          |     |     +--MetalScrollButton [0, 0, 0, 0]          |     +--JTextField [5, 168, 262, 20]          +--JPanel [0, 488, 592, 61] (FlowLayout: 2 children)             +--JPanel [20, 5, 311, 51] (BorderLayout: 3 children)             |  +--JComboBox [5, 21, 87, 25] (MetalComboBoxUI$MetalComboBoxLayoutManager: 2 children)             |  |  +--MetalComboBoxButton [0, 0, 87, 25]             |  |  +--CellRendererPane [0, 0, 0, 0] (null: 1 child)             |  |     +--BasicComboBoxRenderer$UIResource [-61, -18, 0, 0]             |  +--JSlider [92, 21, 200, 25]             |  +--JLabel [292, 21, 14, 25]             +--JPanel [336, 13, 235, 34] (FlowLayout: 2 children)                +--JLabel [7, 9, 106, 16]                +--JPasswordField [118, 7, 110, 20]

Highlights of the Final GUI

Because of the greater complexity of this program’s interface, the code for creating the interface is broken into six methods: createMenuBar(), createCenterPanel(), createNorthPanel(), createSouthPanel(), createDisplayOption-sPanel() and createSaladOptionsPanel().

In lines 121 - 122, the second parameter to the JLabel constructor instructs the JLabel to center whatever text it has to display. Our previous programs didn’t set this parameter on the JLabels so they defaulted to JLabel.LEFT.

In line 124, we set the JLabel’s “opaque” property to true. JLabels are transparent by default, which means that they don’t paint their background. This allows whatever is behind to show through. To make the label’s background yellow, we must set it to yellow, and then call this line to ensure that its background is painted whenever the label is painted.

Line 133 sets the font of the textarea to a 24 point version of whatever the textarea’s default font was.

Lines 136 and 206 make use of JScrollPanes. One JScrollPane contains the textArea and another contains the list so that when the textArea or list contains more text or items than can be displayed, they will become scrollable. JScrollPane is a priceless tool, making a difficult task trivial.

In lines 152, 165, 190, 193 and 217, TitledBorders are responsible for the text and gray outline around these panels. Pretty neat, huh?

Lines 178 – 183 utilize a typical pattern for organizing radio buttons. Radio buttons are usually arranged in groups where only one radio button can be selected at a time. Neither a component nor a container, ButtonGroup can be thought of as a helper class that gives this typical behavior to a group of radio buttons or any other two-state buttons.

In the JSlider constructor (line 222), the first two integer parameters determine the minimum and maximum values the slider can have. The third integer parameter sets the slider’s initial value.

In line 224, we initialize the label’s text to match the slider’s initial value. In the next chapter, sliding the slider will actually update the label.

The integer parameter in the JPasswordField constructor (line 232) sets the number of columns of the field. JPasswordField inherits the columns property from JTextField. Surprisingly, the number of columns has no effect on how many characters the field can contain. It affects the preferred size of the field but not in a very accurate manner. Often the number of columns is a moot point because a layout manager will usually determine the size of its components. In this application, however, the textfield’s container uses FlowLayout which, as you may recall, always sets a component to its preferred size. So, it was important to set the number of columns to a sensible value.

Layout of the Final GUI

For the first time, we used TreePrinterUtils.printLayout() to print the entire window contents rather than just the content pane’s contents. In this expanded (and complete) textual view of the window’s layout, the content pane is listed on the sixth line. It is the second child of a JLayeredPane, which is the second child of a JRootPane, which is the only child of the JFrame. Until now, this chapter intentionally presented a simplified view of the structure of top-level Swing containers. You may never need to know more, but if you would like a complete explanation, please consult the

javadocs for JRootPane. Also of interest in the textual view is the structure of the JMenuBar which doesn’t show the four JMenuItems we added (Why not?). Finally take a look at the structure of the JScrollPanes and the structure of the JComboBox.

The program only uses BorderLayout, FlowLayout and GridLayout, but through the use of multiple nested JPanels, these were enough to produce a complex interface. Components that will be related to each other in the next chapter were generally placed in the same JPanel. The basic logic for which layout manager to use in each JPanel was:

1. If only one of the components in a group should resize when the container resizes, BorderLayout was chosen and that component was placed in the CENTER position. The Panel including the JTextArea was an obvious candidate for BorderLayout. BorderLayout happens to be my favorite layout manager due to its simplicity of use and the way it handles the CENTER component. You can see that I used it in several containers.

2. If the components in a group should be sized uniformly then GridLayout was chosen. GridLayout was an obvious choice for JRadioButton and JCheckBox groups.

3. If the components were to remain at their preferred sizes and not resize when the container is resized, Flow-Layout was chosen. FlowLayout is not one of my favorites but it had its usefulness in a couple panels, too.

Technically and artistically, there are many ways to design an interface. From the technical perspective, I chose multiple containers and simple layout managers because it seemed like an elegant solution to me. However, the entire GUI could possibly have been constructed from one container and a very complicated GridBagLayout. From the artistic perspective, of course, beauty and usability are subjective qualities and I make no claims to the interface’s beauty or usability. Its purpose was to put as many different components into one window as seemed reasonable for a chapter on GUIs, and to serve as the basis for the next chapter. The interface meets this objective. If you don’t like it artistically, design your own. (I really mean that).




Java For Artists(c) The Art, Philosophy, and Science of Object-Oriented Programming
Java For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504052
EAN: 2147483647
Year: 2007
Pages: 452

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net