Buttons on a JPanel with Listeners - top of Musings page

by Nick Duchon

This is an example of putting a lot of buttons onto a JPanel, which is then put onto a JFrame.

Notes:

  1. Since the class HangND already extends JFrame, there is no need to create a new JFrame. Also, the calls in the constructor already have a context - this JFrame.

  2. Again, since HangND extends JFrame, the frame definition stuff can be moved to the constructor, and the code in main is just one line!

  3. This class has NO explicit instance variables - and does not need them to respond to button presses.

  4. You should experiment with the results of turning "pack" and setting or not setting the layout to GridLayout. The results are instructive.

  5. The JPanel to hold the buttons uses GridLayout.

  6. The variables for the JPanel and JButtons are local to the method initAlphabetPanel. References to the objects they create are stored in the AWT data structures. In the case of the JPanel, its reference is part of the JFrame content pane. The references to the JButtons are stored in the JPanel, and in they are also stored in the event listener data structure. Thus, this code (and code in general) will not need to have a separate data structure to hold these items.

  7. The JButton listeners are defined using anonymous inner classes, and their return values are communicated to the main program through the pressedButton method. There are a variety of different ways to approach handling events, but since all of these buttons are returning a single character, and that is the basic piece of information to be handed around, using a single method to handle the values returned by the buttons seems like a clean solution here.

Image:


// File: HangND.java
// Date: Oct 9, 2010
// Author: Nicholas Duchon
// Reference: Liang 8, Hangman game problem series
//       pg 341, 9.31
//       pg 530, 15.17
//       pg 568, 16.35
// Purpose: how to create a panel with lots of buttons,
//       with listeners, efficiently
// Recall: JFrame default layout is BorderLayout
//       JPanel default layout is FlowLayout
// NOTE: check the combinations of setting GridLayout and pack below

importjavax.swing.JFrame;
importjavax.swing.JPanel;
importjavax.swing.JButton;
importjava.awt.BorderLayout;
importjava.awt.GridLayout;
importjava.awt.event.ActionListener;
importjava.awt.event.ActionEvent;
importjava.awt.Color;

public class HangND extends JFrame {

 
public HangND () {
   initAlphabetPanel ();
   getContentPane().setBackground (Color.cyan);
// grey is so boring
  
setTitle ("Hangman Duchon");
   setSize (400, 400);
   setLocationRelativeTo (
null);
   setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//  pack (); // try turning this on and off
   setVisible (true);
 }
// end constructor

 
void initAlphabetPanel () {
   JPanel p =
new JPanel ();
   p.setLayout (
new GridLayout (0, 7)); // try turning this on and off also
   add (p, BorderLayout.PAGE_END);

   
for(inti = 'A'; i <= 'Z'; i++) {
     JButton b =
new JButton (String.format("%c", i));
     p.add (b);

     b.addActionListener (
new ActionListener () {
         
public void actionPerformed (ActionEvent e) {
           pressedButton (e.getActionCommand());
         }
// end listener method
   
   } // end anonymous inner class definition
     ); // end accActionListener parameter

   } // end for each letter

} // end initAlphabetPanel

 
void pressedButton (String s) {
   System.out.println (
"Button pressed: "+ s);
 }
// end pressedButton method

public static void main (String args []) {
   JFrame f =
new HangND ();
 }
// end main
} // end HangND