Jeremy Stein - Journal

« »

Swing Example

Nearly a year ago, I posted some ideas for best practices for swing I neglected to add any examples, but today someone finally asked for one. So I threw together an example of a dialog window that uses composition rather than inheritance. Whew — there sure is a lot of boilerplate code just to get a simple dialog!

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SampleDialog {
    private JFrame parentFrame;
    private JDialog dialog;
    private JTextField field;
      
    private JButton okButton;
    private JButton cancelButton;

    public SampleDialog(JFrame parentFrame) {
        this.parentFrame = parentFrame;
    }

    private void init() {
        this.field = new JTextField();
    
        this.okButton = new JButton("OK");
        this.okButton.addActionListener(new OkButtonListener());

        this.cancelButton = new JButton("Cancel");
        this.cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                close();
            }
        });

        this.dialog = new JDialog(this.parentFrame, "Sample", true);
        this.dialog.getContentPane().add(createPane());
        this.dialog.getRootPane().setDefaultButton(this.okButton);
        setEscapeKeyMap();
        this.dialog.pack();
        this.dialog.setLocationRelativeTo(this.parentFrame);
    }

    private Container createPane() {
        JPanel topPanel = new JPanel(new FlowLayout());
        topPanel.add(new Label("Something"));
        topPanel.add(this.field);

        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS));
        bottomPanel.add(Box.createHorizontalGlue());
        bottomPanel.add(this.okButton);
        bottomPanel.add(Box.createRigidArea(new Dimension(10, 0)));
        bottomPanel.add(this.cancelButton);

        JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.setBorder(BorderFactory.createEmptyBorder(9,9,9,9));
        mainPanel.add(topPanel, BorderLayout.CENTER);
        mainPanel.add(bottomPanel, BorderLayout.PAGE_END);
        return mainPanel;
    }

    private void setEscapeKeyMap(){
        String CANCEL_ACTION_KEY = "CANCEL_ACTION_KEY";
        int noModifiers = 0;
        KeyStroke escapeKey = KeyStroke.getKeyStroke(
            KeyEvent.VK_ESCAPE, noModifiers, false);
        InputMap inputMap = this.dialog.getRootPane().getInputMap(
            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        inputMap.put(escapeKey, CANCEL_ACTION_KEY);
        AbstractAction cancelAction = new AbstractAction(){
            public void actionPerformed(ActionEvent e){
                close();
            }
        }; 
        this.dialog.getRootPane().getActionMap().put(
            CANCEL_ACTION_KEY, cancelAction);
    }

    public void show() {
        if (this.dialog == null) {
            init();
        }

        this.field.setText("Initial value");

        this.dialog.show();
    }

    private void close() {
        this.dialog.hide();
    }
  
    private class OkButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            // Do work
            close();
        }
    }
}

March 16, 2005 12 Comments.

12 Comments

  1. Mark A. Hershberger replied:

    Reason #444 why I don’t love Java.

    March 20th, 2005 at 10:21 pm. Permalink.

  2. kaushalsahu replied:

    this example is good

    November 11th, 2005 at 6:40 am. Permalink.

  3. kaushal replied:

    good example of swing

    November 17th, 2005 at 2:26 am. Permalink.

  4. Arivu replied:

    hi…
    How to compile & use it???

    August 25th, 2006 at 4:57 am. Permalink.

  5. Jeremy replied:

    I’m sorry. That was an example of a particular Swing architecture, not a getting-started example. I highly recommend purchasing a good Java book. Once you’ve built a couple of Swing applications, come back and read the post. Then see if you agree with my philosophy on Swing.

    Good luck!

    August 26th, 2006 at 1:17 pm. Permalink.

  6. Anne replied:

    Jeremy,
    This is excellent work. Now, what do you think of there being a static method named “createAndShowGui” inside each Swing application?
    Anne

    February 20th, 2007 at 3:38 pm. Permalink.

  7. Jeremy Stein replied:

    I don’t get it. Why not just put that work in main?

    February 20th, 2007 at 4:46 pm. Permalink.

  8. Anne replied:

    jeremy,
    Ok, I agree. Another question for you. Could you expain #1 some more in depth? For example, why do you believe a private nested class is best?

    February 21st, 2007 at 6:46 am. Permalink.

  9. Jeremy replied:

    Anne is referring to this quote from Best Practices For Swing:

    You don’t really want your class to be the listener. Would you want other classes to register your class as listening to their events? But even if you were to move the listener to a private nested class (as it should be)…

    The interfaces and public methods of your class should indicate how you want your class to be used. Is your class intended to be an ActionListener? Do you want clients to call actionPerformed? That’s what you’re telling clients when your window class implements ActionListener. You could make it another class, but a general rule-of-thumb is that a utility class used only by one class should be a private nested class. This avoids confusing writers of clients with classes they wouldn’t use. If you want it to be a separate class, at least make it protected.

    February 21st, 2007 at 9:20 am. Permalink.

  10. Anne replied:

    Jeremy,
    This is excellent OO theory in practice. I think we should start a “Best Practices for Swing” website. Your detailed explanations are very clear!!

    February 22nd, 2007 at 6:02 am. Permalink.

  11. Anne replied:

    I think that we could take each of Jeremy’s sentences and write a page or more on each one. He says “I think this calls for composition…” – yes!! In more ways then one. Our great OO industry leaders always emphasize to model your software after the real world. Well, in this case, Swing can be viewed as containers to which we add components – right? So what better way then to model your Swing code by using containment rather then inheritance? A number of OO methodologists favor containment over inheritance. So good job Jeremy!!

    February 22nd, 2007 at 8:30 am. Permalink.

  12. Jeremy replied:

    I think that we could take each of Jeremy’s sentences and write a page or more on each one.

    I assumed you meant that every sentence I write is so meaningful that it deserves an entire article addressing the wisdom behind it. My wife thinks the problem is that my writing is so obtuse and unclear, it would take an article to decipher my cryptic ramblings.

    I chuckle when I read about recommending containment over inheritance. I remember trying to write Visual Basic COM objects to be used in ASP (before .NET). Microsoft recommended containment over inheritance, but it turns out that was only because “inheritance” in Visual Basic was so hacked together and incomplete it was fairly well useless.

    “Is-a” and “has-a” rules seem to break down fairly quickly. I’m permanently scarred by my CS teachers emphasizing that you should “model your software after the real world”. It just doesn’t work. In the real world, windows are composed of glass and wood and they only inherit dust. Those suggestions just don’t work for me. I’ve found that the best way to design your software is to think about the poor schmuck who will come after you to maintain it or write a client against it. Try to make what you’re doing obvious. Don’t be clever; be obvious.

    February 23rd, 2007 at 9:23 am. Permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

« »