Java Swing: удаление анонимного ActionListener из компонента

Я создал массив JButtons с анонимным ActionListeners, и при определенных условиях я хочу удалить все ActionListeners, но для метода .removeActionListeners требуется ActionListener в качестве аргумента. Как я могу удалить прослушиватели действий?

for (int i=0; i < button.length; i++){
    button[i] = new JButton();
    button[i].addActionListener(listener.new ButtonListener());
}

Ответ 1

Вы можете получить их с помощью getActionListeners:

for( JButton currentButton: button ) {
    for( ActionListener al : currentButton.getActionListeners() ) {
        currentButton.removeActionListener( al );
    }
}

Я не уверен, что он будет выброшен ConcurrentModificationException.

Ответ 2

Я понимаю ваш вопрос, и, как предложили другие, повторяя все действия, слушатели из класса клиента могут решить вашу непосредственную проблему.

  • В этом случае то, что вы действительно пытаетесь сделать, это расширить функциональность JButton, и это один из способов решения этой проблемы - расширьте JButton и добавьте метод под названием removeAllActionListeners() (который не принимает никаких параметров).

    • Внутри этого метода вы можете выполнять итерацию через всех слушателей действий и удалить их. Я думаю, что это лучше дизайн, если вы делаете это здесь, чем в класс клиента.
  • Если вы не хотите этого делать, я думаю, что предложение Tom Hawtin использовать состояние в вашем ButtonListener - хорошая идея.

  • В противном случае у вас всегда есть возможность отказаться от очень "хакерского" способа, который заключается в том, чтобы хранить коллекцию слушателей действий в вашем классе клиента.

    • Map<JButton, ButtonListener> (если всегда будет только один прослушиватель на кнопку) или
    • Map<JButton, List<ButtonListener>> (если может быть несколько слушателей на кнопку) - это то, что я могу использовать.

Я думаю, что методы 1 и 2 предпочтительны, а метод 3 указывает на плохой дизайн (но гораздо проще взломать вместе).

Обратите внимание: если вы действительно используете метод 1 или что-то подобное, убедитесь, что методы или атрибуты, к которым вы обращаетесь, являются потокобезопасными (как упоминается OscarRyz), а если нет, используйте synchronized для обеспечения безопасности потока.

Ответ 3

Вы не можете. Никто не ссылается на эти объекты. Чтобы их можно было удалить, вам необходимо сохранить его как член/переменную данных в вашем коде, а затем передать эту переменную методу removeActionListener(). Однако вы можете использовать метод getActionListeners() для получения массива всех объектов ActionListener, связанных с Button. Затем вам нужно будет выяснить, какой из них удалить, но если есть только один, это должно быть легко; -)