Общий прослушиватель действий для 3 кнопок

У меня проблемы с дизайном моего кода. У меня есть 3 кнопки не в группе кнопок. Я хочу - на основе выбранной кнопки - выполнить действие. Теперь действие требует модификации объекта в классе. Это означает, что я не могу использовать внутренний класс, потому что у него нет доступа к внешнему. Если бы я мог добавить прослушиватель событий в группу кнопок, это было бы намного проще, но, насколько я понимаю, мне понадобится обработчик событий для каждого переключателя, правильно ли это? Если нет, как еще я могу это сделать? Спасибо

Быстрый пример

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();
       }.....
   }
}

person Biscuit128    schedule 13.03.2013    source источник
comment
Это утверждение неверно: я не могу использовать внутренний класс, потому что у него нет доступа к внешнему, а внутренний класс не является статическим.   -  person gontard    schedule 13.03.2013
comment
Это первый раз в моей жизни, когда я вижу числа, используемые в качестве имен!   -  person Kakalokia    schedule 13.03.2013
comment
@Али быстро печатает :D   -  person Biscuit128    schedule 13.03.2013


Ответы (2)


Вы можете установить один и тот же слушатель для всех ваших кнопок.

Псевдокод:

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

listener = new ActionListener() {
...
}


radioButton1.addActionListener(listener);
radioButton2.addActionListener(listener);
radioButton3.addActionListener(listener);
person Jean Waghetti    schedule 13.03.2013
comment
Я бы рекомендовал анонимные классы. - person Kakalokia; 13.03.2013
comment
@Ali Вам придется ввести тело анонимных классов 3 раза, и вы не получите выгоды от одной ссылки. Так что анонимные классы в этом примере не годятся. - person FazoM; 13.03.2013
comment
@fazomisiek Почему? Один анонимный класс, реализующий ActionListener, может обрабатывать события для каждой из трех переключателей. - person Jean Waghetti; 13.03.2013

Это должно проиллюстрировать, как вы можете использовать внутренний класс:

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();
        }
    }
}
  • Обратите внимание, что внутренний класс не является статическим, как указано в комментарии Гонтарда, поэтому имеет видимость для myObject. И безопаснее всего держать это в тайне.

Часто бывает полезно иметь один слушатель, обрабатывающий все события, как в этом случае. Однако есть и другие случаи, когда вы хотите, чтобы ваша обработка событий была более специфичной для каждого компонента. Например, в этих случаях событие radioThree может вызвать событие, а поскольку эти кнопки не входят в группу, возможно, что radioOne все еще находится в выбранном состоянии. Этот единственный обработчик сработает и будет действовать только на первом радио. Хотя одним из способов исправить это было бы добавить проверки для источника, например:

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();
}

Другой способ — использовать один слушатель для каждого компонента. Вот где анонимный класс очень удобен:

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

Один из моих любимых шаблонов, особенно если работа нетривиальна, заключается в том, чтобы сначала создать метод для выполнения работы, а затем вызвать его из слушателя. Я также оборачиваю вызов в SwingUtilities.invokeLater(), чтобы получить работу от потока событий Swing.

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();
                    }
                });
            }
        });
    }
}

Это обеспечивает две приятные функции:

  1. Он инкапсулирует вашу работу в метод, обеспечивающий программный доступ, если это потребуется позже.
  2. Это гарантирует, что работа метода не связана с потоком событий Swing, поэтому ваш графический интерфейс не зависнет во время интенсивной обработки.
person SeKa    schedule 14.03.2013