Question

I am having trouble with the design of my code. I have 3 buttons not in a button group. I want to - based on the selected button - perform an action. Now the action requires a modification of an object in the class. This means i cannot use an inner class because this does not have access to the outer. If i could add an event listener to a button group this would be much easier but as i see it i will need an event handler for each radio button, is this correct? If not how else can i do it? Thanks

A quick example

public class Test(){
    RadioButton 1 = new RadoButton();
    RadioButton 2 = new RadoButton();
    RadioButton 3 = new RadoButton();
    Object myObject = new Object();

   public void clickEvent(){
       if(1.isSelected()){
           myObject.doOne();
       }else if(2.isSelected()){
           myObject.doTwo();
       }.....
   }
}
Was it helpful?

Solution

You can set the same listener to all your buttons.

Pseudo code:

radioButton1 = new RadioButton();
radioButton2 = new RadioButton();
radioButton3 = new RadioButton();

listener = new ActionListener() {
...
}


radioButton1.addActionListener(listener);
radioButton2.addActionListener(listener);
radioButton3.addActionListener(listener);

OTHER TIPS

This is to illustrate how you can use an inner class:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JRadioButton;

public class TestInnerClass {

    JRadioButton radioOne = new JRadioButton();
    JRadioButton radioTwo = new JRadioButton();
    JRadioButton radioThree = new JRadioButton();
    Object myObject = new Object();

    public TestInnerClass() {
        ActionListener myInnerClass = new MyActionListener();
        radioOne.addActionListener(myInnerClass);
        radioTwo.addActionListener(myInnerClass);
        radioThree.addActionListener(myInnerClass);
    }

    private class MyActionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            if(radioOne.isSelected()) myObject.toString();
            else if(radioTwo.isSelected()) myObject.notify();
            else if(radioThree.isSelected()) myObject.getClass().getName();
        }
    }
}
  • Note how the inner class is not static, as stated in gontard's comment, so does have visibility to myObject. And it's safest to keep it private.

It's often good to have one listener handle all events, as in this case. There are, however, other cases where you want your event handling more specific to each component. For example, in these cases, radioThree could trigger the event, and since these buttons are not in a group it might be possible that radioOne is still in the selected state. This single handler will fire and act only on the first radio. While one way to fix this would be to add checks for the source, as in:

public void actionPerformed(ActionEvent event) {
    if(event.getSource() == radioOne && radioOne.isSelected()) 
        myObject.toString();
    if(event.getSource() == radioTwo && radioTwo.isSelected()) 
        myObject.notify();
    if(event.getSource() == radioThree && radioThree.isSelected())
        myObject.getClass().getName();
}

Another way would be to use one listener for each component. That's where the anonymous class comes in very handy:

radioOne.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        myObject.doOne();
    }
}); 

One of my favorite patterns, especially if the work is non-trivial, is to first create a method to do the work, then call it from the listener. I also wrap the call in SwingUtilities.invokeLater() to get the work off the Swing Event Thread.

public class Test {

    JRadioButton radioOne = new JRadioButton();

    Object myObject = new Object();

    private void handleRadioOne() {
        myObject.toString();
        // etc, etc.
    }

    public Test() {

        radioOne.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        handleRadioOne();
                    }
                });
            }
        });
    }
}

This provides two nice features:

  1. It encapsulates your action work into a method allowing for programmatic access if later desired
  2. It ensures that the method's work stays off the Swing Event Thread, so your GUI won't hang up during intensive processing
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top