views:

37

answers:

2

I'm learning Swing and have composed an interface using a series of get methods to add components. Is it a good practise to add a Listener inside a get method as follows? I'd like to make things as decoupled as possible.

 private JButton getConnectButton() {
  if (connectButton == null) {
   connectButton = new JButton();
   connectButton.setText("Connect");
   connectButton.setSize(new Dimension(81, 16));
   connectButton.setLocation(new Point(410, 5));

   connectButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
     // actionPerformed code goes here
    }
   });

  }
  return connectButton;
 }
+1  A: 

It seems like you're implementing some lazy initialization of the connectButton. That's probably fine, although, I would do it like this:

private void createButton() {
    connectButton = new JButton(new AbstractAction("Connect") {
        public void actionPerformed(ActionEvent e) {
            // actionPerformed code goes here
        }
    });
    connectButton.setText("Connect");

    // Rely on some LayoutManager!
    //connectButton.setSize(new Dimension(81, 16));
    //connectButton.setLocation(new Point(410, 5));
}

private synchronized JButton getConnectButton() {
    if (connectButton == null)
        createButton();

    return connectButton;
}

Note the use of synchronized. It ensures that the following scenario won't happen:

  • Thread 1 calls getConnectButton() and sees connectButton == null
  • Thread 2 calls getConnectButton() and sees connectButton == null
  • Thread 1 calls createButton
  • Thread 2 calls createButton.

There are probably nicer ways to synchronize the button-construction, but this is one way.

aioobe
Thanks. I didn't know the lazy initialization approach could be used when it comes to Swing. This is how Visual Editor encodes components. I'll keep a copy of your reply handy for when this is needed.
James P.
+2  A: 

From my extensive practice as a Swing developer I can tell you that it's not good practice to obtain component instances in this manner(via getters). I generally setup the UI for a Frame/Dialog in some method like initComponents() and afterwards add all the listeners in some method like addListeners(). I'm not sure if that there is a single best practice as how to do things - there a lot of options and personal preferences. Generally, however, lazy init of components that you'll need anyways(like this button I presume) is unneeded.

Also - you should really consider using some layout manager such a MiG and avoid hardcoded component sizes.

Bozhidar Batsov
In addition, I would suggest defining Components as private final and instantiate them directly in their declaration.
jfpoilpret
Only if they need to be accessible from other parts of the frame/dialog. Labels, for instance, don't warrant even a local variable most of the time. Buttons that won't be enabled/disabled conditionally don't need to be fields as well. There is no generic recipe for that I think - it all depends on the situation. But certainly one should strive to minimize the number of fields.
Bozhidar Batsov
I appreciate feedback that involves experience. Tell me, how do you organize components in general? Do you have one big monolithical class where all the components are described or do you them into separate panel classes? I've also heard good things about MiG and will give it a try.
James P.