Lab exercise #7: An introduction to the Swing library classes

Course links

External links

Visible talliers

Our goal in this lab is to provide a graphical user interface to the basic Tallier class previously defined.

  1. Open Eclipse and set up to create the definition of a new class, VisibleTallier, that extends Tallier.
  2. The main method for this class will do nothing more than invoke the VisibleTallier constructor once, to launch the graphical user interface. All subsequent operations will be responses to user manipulation of the GUI. Write the main method.
  3. The VisibleTallier constructor will be quite elaborate, since it needs to initialize and package all the components of the GUI. At this point, just write a stub -- the heading for the constructor and a pair of empty braces for its body.

The JFrame class

The window in which our application runs will be a JFrame.

  1. Add a JFrame field called frame to the VisibleTallier class.
  2. Inside the VisibleTallier constructor, initialize this field by calling a JFrame constructor with appropriate arguments. Use the one-argument constructor that takes a title string, which will be displayed in the title bar at the top of the window.
  3. Immediately after constructing frame, send it the setDefaultCloseOperation message, providing the argument that indicates that the application should exit as soon as the frame has been closed. (Recall that the JFrame class defines a constant, EXIT_ON_CLOSE, that denotes the integer with this conventional meaning.)

The JLabel class

We'll display the current reading of the counter field of the tally in a JLabel.

  1. Add a JLabel field called numeral to the VisibleTallier class.
  2. Inside the VisibleTallier constructor, initialize this field by calling a JLabel constructor with appropriate arguments. Use the constructor that takes as arguments a text string to be displayed (showing the initial reading of counter) and a integer indicating the horizontal alignment (whether the text is to be left-justified, centered, or right-justified). The SwingConstants class contains some readable names for these integers (e.g., SwingConstants.CENTER is the integer that signifies centered alignment).
  3. The default font that JLabel uses in rendering text is kind of small and thin for this particular application. Immediately after constructing the JLabel, send it the setFont message to tell it to use a larger, bolder font. The setFont method takes a Font object as its argument -- you'll need to construct one, supplying to the constructor the name of the font (e.g., "Courier"), the font style (e.g., Font.BOLD), and the font size, expressed in "points" (there are 72.27 points in an inch).

The JButton class

The only user interactions with a VisibleTallier will consist of clicking appropriate buttons. We'll offer three: one ("tally") to increment the counter, one ("reset") to reset it to zero, and one ("quit") to exit from the application.

  1. Add a JButton field for each of these buttons. Call these fields tallyButton, resetButton, and quitButton.
  2. Inside the VisibleTallier constructor, initialize each of these fields by calling a JButton constructor with appropriate arguments.
  3. We'll want to associate each of these buttons with an ActionListener that implements an actionPerformed method that carries out the operation associated with that button. Write the body of an anonymous class containing the following actionPerformed method:
    public void actionPerformed(ActionEvent evt) {
        tally();
        numeral.setText(String.valueOf(report()));
    }
    
    This invokes the tally method, inherited from Tallier, to increment counter, then updates the numeral field so that it displays the new value.
  4. Write the constructor for an object of this anonymous class. Associate this object with tallyButton by sending tallyButton the addActionListener message, with the anonymous object as its argument.
  5. Similarly, write an ActionListener that resets counter and associate it with resetButton.
  6. Similarly, write an ActionListener that closes frame and associate it with quitButton. (To close frame under program control, send it the dispose message.)

The JPanel class

A JPanel is used to collect related widgets into a single structure. We'll use it to assemble the three buttons into a group.

  1. In the constructor for VisibleTallier, declare a local variable of type JPanel and initialize it by calling the appropriate constructor. Give the constructor a GridLayout object as its argument. You can use the zero-argument GridLayout constructor to get one.
  2. Send three add messages to the JPanel to add each of the buttons in turn.
  3. Add the completed JPanel to the content pane inside frame by sending frame.getContentPane the appropriate add message. By default, frame uses a BorderLayout for its components, so you can place the buttons at the top of the frame by giving add the second argument BorderLayout.NORTH.
  4. Similarly add numeral to frame's content pane with another add message. Position it at BorderLayout.CENTER.

Finishing touches

  1. At the end of the constructor, send frame the pack message to fit the window size to the sizes of the components.
  2. After that, send the setVisible message to frame, giving it the argument true.

You should now have a working application. Play with it to make sure that everything works correctly.

Extras

  1. The black-on-gray defaults make the interface a little drab. Every JComponent has setBackground and setForeground methods that one can use to change the color scheme for that component. Arrange for the current tally to be displayed in red against a white background (or, if you prefer, in green against a purple background). Change the colors of the buttons to harmonize with the new display.
  2. Add a button that decrements the counter, if it is positive. (If the counter is 0, clicking the button should have no effect.)
  3. Add a set of ten digit buttons and an ENTER button, so that the user can input a new value to be stored in the counter by clicking on the digits of the new value and then pressing ENTER to store it. How should the display be updated as the digits of the new value are collected?