I l@ve RuBoard |
![]() ![]() |
5.4 The JButton ClassJButton is the simplest of the button types, adding very little to what is provided by the AbstractButton class. JButtons are buttons that are not toggled on and off but instead act as push buttons, which invoke some action when clicked. Figure 5-2 shows what these buttons look like in four of the Swing L&Fs. Figure 5-2. JButtons in four L&Fs![]() 5.4.1 PropertiesThe JButton class inherits most of its properties and default values from its superclasses. The exceptions to this are shown in Table 5-9. The model property is set to a new instance of DefaultButtonModel when a JButton is created.
The defaultButton property indicates whether the button is activated by default when some event occurs within the JRootPane containing the button. Typically, the event that would trigger the button would be an Enter key press, but this is actually up to the L&F implementation. The defaultButton property cannot be set directly. Instead, it is set by telling the JRootPane which button should be the default. (We'll cover JRootPane in Chapter 8—at this point, it's enough to know that the Swing containers JApplet, JDialog, JFrame, and JWindow all use a JRootPane as their primary content container.) If the button is inside one of these Swing containers, this property may be true. The other new property, defaultCapable, indicates whether the button may be set as a root pane's default button. A button may be treated only as the default button if this property is set to true. 5.4.2 Using the Default ButtonHere's a quick example showing how the default button property can be used: // DefaultButtonExample.java // import javax.swing.*; import java.awt.*; // Example using defaultButton and JRootPane.setDefaultButton( ) public class DefaultButtonExample { public static void main(String[] args) { // Create some buttons. JButton ok = new JButton("OK"); JButton cancel = new JButton("Cancel"); JPanel buttonPanel = new JPanel( ); buttonPanel.add(ok); buttonPanel.add(cancel); JLabel msg = new JLabel("Is this OK?", JLabel.CENTER); // Create a frame, get its root pane, and set the OK button as the default. This // button is pressed if we press the Enter key while the frame has focus. JFrame f = new JFrame( ); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JRootPane root = f.getRootPane( ); root.setDefaultButton(ok); // Layout and display Container content = f.getContentPane( ); content.add(msg, BorderLayout.CENTER); content.add(buttonPanel, BorderLayout.SOUTH); f.setSize(200,100); f.setVisible(true); } } The first thing we do here is create two buttons and a label. We then create a JFrame and get its "root pane." Next, we call this pane's setDefaultButton( ) method, passing in a reference to the OK button. When this program runs, the OK button is drawn with a different border around it, as shown with the Metal L&F in Figure 5-3. More importantly, when we press Enter while the frame has focus, the OK button is pressed automatically. Figure 5-3. Default button![]() 5.4.3 EventsJButton does not define any new events, but it's important to understand which of the events defined by its superclasses are fired when the button is pressed. The most important thing to know about JButton events is that JButtons fire ActionEvents when they are clicked. This type of event is sent after the button is released, and only if the button is still armed (meaning that the cursor is still over the button). The following example creates event listeners for action, change, and item events to show which events are fired when we press the button: // JButtonEvents.java // import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class JButtonEvents { public static void main(String[] args) { JButton jb = new JButton("Press Me"); jb.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent ev) { System.out.println("ActionEvent!"); } }); jb.addItemListener(new ItemListener( ) { public void itemStateChanged(ItemEvent ev) { System.out.println("ItemEvent!"); } }); jb.addChangeListener(new ChangeListener( ) { public void stateChanged(ChangeEvent ev) { System.out.println("ChangeEvent!"); } }); JFrame f = new JFrame( ); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.getContentPane( ).add(jb); f.pack( ); f.setVisible(true); } } Running this program and pressing the button produces the following output: ChangeEvent! ChangeEvent! When the button is released, the following additional output is produced: ActionEvent! ChangeEvent! The initial change events are fired, indicating that the button is armed and pressed. When the button is released, the action event is fired, along with another change event to indicate that the button is no longer pressed. Pressing the button a second time results in only a single change event, followed by the action event and change event when the button is released. This is because the button's armed property is still set to true after the button is clicked. This property is set to false again only if you hold the mouse button down and then move the cursor away from the button. If the button is released while the pointer is no longer over the button, no ActionEvent is fired. In practice, you are typically interested only in the ActionEvents fired by a JButton. 5.4.4 Constructors
5.4.5 Using ActionsThe following example creates four Action objects and uses them to create buttons (and to create menu items, just to show how easy it is). Each button (and menu) takes its text, icon, mnemonic, toolTip, and enabled status from the Action. If an Action changes one or more of these, the button (and menu) reflects the change automatically. Figure 5-4 shows an example of this: both the button and the menu item change from "Go to channel 9" in their enabled state to "Go to channel 2" in their disabled state when the user clicks on (or invokes via the mnemonic with Alt-S)[4] the Set `Go to' channel button.
Figure 5-4. ActionExample before and after clicking on the Set `Go to' channel button![]() // ActionExample.java // import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ActionExample extends JFrame { public static final int MIN_CHANNEL = 2; public static final int MAX_CHANNEL = 13; private int currentChannel = MIN_CHANNEL; private int favoriteChannel = 9; private JLabel channelLabel = new JLabel( ); private Action upAction = new UpAction( ); private Action downAction = new DownAction( ); private GotoFavoriteAction gotoFavoriteAction = new GotoFavoriteAction( ); private Action setFavoriteAction = new SetFavoriteAction( ); public class UpAction extends AbstractAction { public UpAction( ) { putValue(NAME, "Channel Up"); putValue(SMALL_ICON, new ImageIcon("images/up.gif")); putValue(SHORT_DESCRIPTION, "Increment the channel number"); putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_U)); } public void actionPerformed(ActionEvent ae) { setChannel(currentChannel+1); } } public class DownAction extends AbstractAction { public DownAction( ) { putValue(NAME, "Channel Down"); putValue(SMALL_ICON, new ImageIcon("images/down.gif")); putValue(SHORT_DESCRIPTION, "Decrement the channel number"); putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_D)); } public void actionPerformed(ActionEvent ae) { setChannel(currentChannel-1); } } public class GotoFavoriteAction extends AbstractAction { public GotoFavoriteAction( ) { putValue(SMALL_ICON, new ImageIcon("images/fav.gif")); putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_G)); updateProperties( ); } public void updateProperties( ) { putValue(NAME, "Go to channel "+favoriteChannel); putValue(SHORT_DESCRIPTION, "Change the channel to "+favoriteChannel); } public void actionPerformed(ActionEvent ae) { setChannel(favoriteChannel); } } public class SetFavoriteAction extends AbstractAction { public SetFavoriteAction( ) { putValue(NAME, "Set 'Go to' channel"); putValue(SMALL_ICON, new ImageIcon("images/set.gif")); putValue(SHORT_DESCRIPTION, "Make current channel the Favorite channel"); putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_S)); } public void actionPerformed(ActionEvent ae) { favoriteChannel = currentChannel; gotoFavoriteAction.updateProperties( ); setEnabled(false); gotoFavoriteAction.setEnabled(false); } } public ActionExample( ) { super("ActionExample"); setChannel(currentChannel); // Enable/disable the Actions as appropriate. channelLabel.setHorizontalAlignment(JLabel.CENTER); channelLabel.setFont(new Font("Serif", Font.PLAIN, 32)); getContentPane( ).add(channelLabel, BorderLayout.NORTH); JPanel buttonPanel = new JPanel(new GridLayout(2, 2, 16, 6)); buttonPanel.setBorder(BorderFactory.createEmptyBorder(6, 16, 16, 16)); getContentPane( ).add(buttonPanel, BorderLayout.CENTER); buttonPanel.add(new JButton(upAction)); buttonPanel.add(new JButton(gotoFavoriteAction)); buttonPanel.add(new JButton(downAction)); buttonPanel.add(new JButton(setFavoriteAction)); JMenuBar mb = new JMenuBar( ); JMenu menu = new JMenu("Channel"); menu.add(new JMenuItem(upAction)); menu.add(new JMenuItem(downAction)); menu.addSeparator( ); menu.add(new JMenuItem(gotoFavoriteAction)); menu.add(new JMenuItem(setFavoriteAction)); mb.add(menu); setJMenuBar(mb); } public void setChannel(int chan) { currentChannel = chan; channelLabel.setText("Now tuned to channel: "+currentChannel); // Enable/disable the Actions as appropriate. downAction.setEnabled(currentChannel > MIN_CHANNEL); upAction.setEnabled(currentChannel < MAX_CHANNEL); gotoFavoriteAction.setEnabled(currentChannel != favoriteChannel); setFavoriteAction.setEnabled(currentChannel != favoriteChannel); } public static void main(String argv[]) { JFrame f = new ActionExample( ); f.setSize(400, 180); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); } } 5.4.6 Fancy ButtonsWhile looking at AbstractButton, we learned that quite a few things can be done with Swing buttons to make them more visually interesting. In this example, we'll see how we can spice up a user interface by adding rollover and selected icons to our buttons. We'll also take away the button borders, focus painting, and fill content area to give our display a nice clean look. // FancyButton.java // import javax.swing.*; import java.awt.*; public class FancyButton extends JButton { // Create a JButton that does not show focus, does not paint a border, and displays // different icons when rolled over and pressed. public FancyButton(Icon icon, Icon pressed, Icon rollover) { super(icon); setFocusPainted(false); setRolloverEnabled(true); setRolloverIcon(rollover); setPressedIcon(pressed); setBorderPainted(false); setContentAreaFilled(false); } // A simple test program public static void main(String[] args) { FancyButton b1 = new FancyButton( new ImageIcon("images/redcube.gif"), new ImageIcon("images/redpaw.gif"), new ImageIcon("images/reddiamond.gif")); FancyButton b2 = new FancyButton( new ImageIcon("images/bluecube.gif"), new ImageIcon("images/bluepaw.gif"), new ImageIcon("images/bluediamond.gif")); JFrame f = new JFrame( ); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container c = f.getContentPane( ); c.setLayout(new FlowLayout( )); c.add(b1); c.add(b2); f.pack( ); f.setVisible(true); } } Figure 5-5 shows our new button class with the different states of the buttons. Of course, this is just one fancy button implementation. You can create your own special button classes using some or all of the features shown in FancyButton, as well as other features, such as adding icons for other button states. Figure 5-5. Buttons using "rollover" and "pressed" icons![]() ![]() |
I l@ve RuBoard |
![]() ![]() |