Компоновка компонентов Swing: как добавить возможность добавления ActionListeners?

Я хочу создать (простой, надеюсь) настраиваемый компонент Swing, составив несколько существующих компонентов. В моем случае это переключатель включения-выключения, который состоит из JLabel и двух JButtons для On и Off. Я начинаю OnOffSwitch, расширяя JPanel. Конструктор добавляет подкомпоненты и устанавливает себя как ActionListener для кнопок. Класс имеет метод isOn () для запроса текущего состояния компонента.

Теперь я хочу добавить возможность добавлять ActionListeners в class OnOffSwitch. Я ожидал, что эта функциональность будет бесплатной благодаря расширению компонента Swing, такого как JPanel, но JPanel не обладает этой функциональностью. По внешнему виду источников каждый компонент Swing, который имеет эту функциональность, повторно реализует его сам: добавление слушателей в список, обстрел ActionEvents и т. Д.

Каков правильный способ добиться того, чего я хочу? Я могу скопировать / вставить этот код из различных компонентов Swing (или переписать его), или я могу реализовать свой собственный интерфейс OnOffSwitchListener. Чтобы быть последовательным, кажется, что все мои компоненты должны использовать ActionListeners.

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

Я предпочел бы состав над наследованием. У вас есть пользовательский интерфейс, в котором есть элементы данных Swing, и дайте ему методы для добавления и удаления Listeners по мере необходимости. Вы можете изменить поведение таким образом, не переписывая UI-class. Это не что иное, как контейнер.

public class MyUI { private Button b = new Button(); public void addButtonListener(ActionListener listener) { this.b.addActionListener(listener); } } 

Я бы использовал JToggelButton , как показано здесь , или делегировать содержащиеся кнопки, как предлагает @duffymo. Если вам действительно нужен пользовательский OnOffSwitchEvent , стандартная проводка изложена в EventListenerList , экземпляр которой содержится в каждом JComponent .

Добавление: Вот пример делегирования ButtonGroup содержащей две кнопки. Метка украшена символом, но любая реализация Icon еще более гибкая.

BttonGroupTest iamge

 import java.awt.Color; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ButtonGroup; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JToggleButton; /** @see https://stackoverflow.com/questions/6035834 */ public class ButtonGroupTest extends JComponent { private static final String ON = "On"; private static final String OFF = "Off"; private final JToggleButton bOn = new JToggleButton(ON); private final JToggleButton bOff = new JToggleButton(OFF); private final JLabel label = new JLabel(" \u2301 "); private final ButtonHandler handler = new ButtonHandler(); public ButtonGroupTest() { this.setLayout(new FlowLayout()); label.setOpaque(true); label.setBackground(Color.red); label.setFont(label.getFont().deriveFont(36f)); ButtonGroup bg = new ButtonGroup(); this.add(bOn); bg.add(bOn); bOn.setSelected(true); bOn.addActionListener(handler); this.add(label); this.add(bOff); bg.add(bOff); bOff.addActionListener(handler); } public void addActionListener(ActionListener listener) { bOn.addActionListener(listener); bOff.addActionListener(listener); } private class ButtonHandler implements ActionListener { @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (ON.equals(cmd)) { label.setBackground(Color.red); } else { label.setBackground(Color.black); } } } private void display() { JFrame f = new JFrame("ButtonGroupTest"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(this); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new ButtonGroupTest().display(); } }); } } 

По внешнему виду источников каждый компонент Swing, который имеет эту функциональность [ActionListener], повторно реализует его сам: добавление слушателей в список, запуск ActionEvents и т. Д.

Ага. Это то, что вам нужно сделать, когда вы пишете пользовательский компонент Swing.

Как вы говорите, вы можете скопировать код ActionListener из существующего компонента Swing,

Давайте будем гением компьютера.