Tutorial 9 - GUI Widgets
A Graphical User Interface (GUI) is a visual paradigm which allows users to communicate with programs in an intuitive way. Features include widgets (aka controls) and event driven activities. Users expect a graphical interface!
Java has two GUI packages, the original Abstract Windows Toolkit (AWT) and the newer Swing. AWT uses the native operating system's window routines so the visual effect is dependent on the run-time system platform. Swing allows three visual modes: a unified look and feel [the default], the native platform look, or a specific platform's look. Swing is built on the original objects and framework of AWT. Swing components have the prefix J to distinguish them from the original AWT ones (eg JFrame instead of Frame). To include Swing GUI components and methods in your project you must import the java.awt.*, java.awt.event.* and javax.swing.* packages. SwingSet 3 demos the Swing widgets. A GUI reference with many examples can be found in the Guidebook. Intermediate|Advanced
Containers: Windows and Content Panes
Containers are components that are used to hold and group widgets such as text fields and checkboxes and other components. Methods common to many containers include: add(), pack(), requestFocus() and setToolTipText().
Windows are top-level containers which interface to the operating system's window manager. Their types are: Primary (adorned with minimize, maximize and close buttons) [JFrame]; Secondary [JDialog]; Plain (no border - used for splash screens) [JWindow] and XHTML document [JApplet].
JFrame is the most commonly used top-level container. It adds basic functionality such as minimize, maximize, close, title and border to basic frames and windows. Some important JFrame methods are: getTitle(), setBounds(x,y,w,h), setLocation(x,y), setMaximumSize(w,h), setMinimumSize(w,h), setPreferredSize(w,h), setResizable(bool), setSize(w,h), setTitle(str) and setVisible(bool). setDefaultCloseOperation(EXIT_ON_CLOSE) enables the close icon.
Content panes are lower level containers such as JPanel, JInternalFrame, JOptionPane, JLayeredPane, JScrollPane, JSplitPane and JTabbedPane which organize the layout structure when multiple controls are being used. JInternalFrame is an adorned lower-level frame used with MDI (Multiple Document Interface) to prevent document overlapping.
JPanel is the most commonly used content pane. An instance of the pane is created and then added to a frame. The add(widgetName) method allows widgets (ie GUI controls) to be added to the pane. layout managers control the way widgets are added. JPanel defaults to FlowLayout. Other content panes default to BorderLayout.
The following is a simple template that creates a JFrame container class using inheritance. The created subclass then adds a JPanel. This custom class will form the basis of many of our GUI examples.
Colors and Fonts
Colors are set using awt Color class constants or created (with transparency) using Color(red, green, blue, [alpha]) where the parameters are integer [0 - 255] or float [0.0 - 1.0]. An alpha level of 255 or 1.0 yields opaque [default]. For example: skyblue is 135,206,235 (ie. 87CEEB hex).
Background colors are set with setBackground(color_obj). Text colors are set with either setColor(color_obj) or the setForeGround(color_obj) depending on the object. Color settings are read using the integer methods: getRGB(), getRed(), getGreen(), getBlue() and getAlpha().
Font objects are created from Font class objects,
eg Font bigFont=new Font("TimesRoman",Font.ITALIC,24);
Note that the parameters are family, style (as a Font class constant) and point size. Style is one of PLAIN, ITALIC or BOLD. Other objects can use the new font style by calling the setFont(fontObject) method.
FontMetrics defines a class that accesses the height information of a font in pixels. The class methods are: getLeading(), getAscent(), getDescent() and getHeight() [overall dimension].
Borders are used to separate or group widgets in a logical manner. They also 'dress up' the GUI. Border classes are imported from the javax.swing.border package. BevelBorder and SoftBevelBorder can be applied to buttons to give them a 3D look. EmptyBorder is used to 'pad' a widget with spacing. EtchedBorder and LineBorder separate widgets or panes for logical grouping. MatteBorder allows images or colors to be used to construct the border areas. TitledBorder allows adding a 'fieldset' frame and a 'legend' caption to an object such as a button group. An example of a titled border object is:
Border blackline=BorderFactory.createLineBorder(Color.black); TitledBorder tb=new TitledBorder(border,"legend");
Any object can use the setBorder(border_obj) method to establish a border around it.
Line separators are used for visual separation of components in a panel. They are constructed with JSeparator(orient). Lines are oriented using either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
Labels and Icons
Labels are non-interactive text objects most commonly used as prompts. They are created using the JLabel() constructor with the required text as the first parameter. Another parameter can be added using a SwingConstant value to set horizontal alignment. Vertical alignment is through the setVerticalAlignment() method. The contents of a label can be changed with the setText() method.
Icons can be easily added to labels or other controls either to brand, dress up, or aid accessibility. Icons are constructed from the ImageIcon class and then added as a parameter to the label (or other) control. An extra parameter can be used to control the position of the text relative to the icon. It must use one of the SwingConstants values.
ImageIcon icon=new ImageIcon("smile.gif"); JLabel label=new JLabel("hello",icon,SwingConstants.RIGHT); pane.add(label);
GUIs are event-based as they respond to user actions such as buttons, keyboard input and mouse activities. Java uses event listeners to monitor activity on specified objects and react to specific conditions. Check the appendix for a listing of event listeners.
The first step in adding an event handler is to add the phrase implements ***Listener (where *** is the appropriate event) to the class header to set up an interface. Register event listeners for a widget using the add***Listener(this) method. The reserved word this indicates that the required (by implements ***Listener) handler method called ***Performed() will be included in the current class.
The difficulty with this technique (ie event sharing) is that it is awkward to program for many buttons and widgets. Extended if statements or switch constructs make code hard to maintain. Inner (ie nested) class event handlers allow handler routines to be written for specific objects. For example, instead of using the addActionListener(this) method for several buttons you can have each button call its own inner class. Function code can still be mixed into GUI code.
NOTE: The implements clause is now placed in each inner class header and not in the main class header. Also the listener registration is of a specific Listener_class object, not the generic this.
Anonymous inner classes have no name (hence no name conflict) and are used when only one instance of the class is required. They also do not have constructors. Anonymous inner classes are most often found in event listeners with very simple actions. Beware! Anonymous listeners intermix action code with the GUI object. This is contrary to the separation of worker code from GUI that is a part of clean design. Avoid this construction if possible.
As event classes are interfaces, all methods within that event must be implemented. Adapter classes provide default do-nothing methods which you can chose to override. This example uses the WindowAdapter class to avoid coding all window events.
There are three types of mouse events: motion, wheel and button clicks. Each has their own listener but adapters can be used to react to combined events. Oracle has examples of many mouse event situations. My simplified mouseMotionDemo uses MVC design principles and adds a status bar using BorderLayout.