Составление компонентов Swing: как добавить возможность добавления ActionListeners? - PullRequest
2 голосов
/ 17 мая 2011

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

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

Ответы [ 3 ]

7 голосов
/ 17 мая 2011

Я бы использовал 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();
            }
        });
    }
}
5 голосов
/ 17 мая 2011

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

Я бы предпочел композицию наследованию. Иметь класс пользовательского интерфейса, который имеет члены данных Swing, и давать ему методы для добавления и удаления прослушивателей по мере необходимости Таким образом, вы можете изменить поведение без необходимости переписывать класс пользовательского интерфейса. Это не более чем контейнер.

public class MyUI
{
    private Button b = new Button();

    public void addButtonListener(ActionListener listener) { this.b.addActionListener(listener); }
}
3 голосов
/ 17 мая 2011

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

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

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

...