Swing: как привязать контейнер к JRadioButton?

У меня есть куча динамически добавляемых панелей, которые содержат переключатель и панель с несколькими метками, привязанными к переключателю. Предположим, у меня есть кнопка, которая должна извлекать контейнер с метками, привязанными к выбранному переключателю, или, скажем, другими словами, данные привязываются к выбранному переключателю. Но как получить этот контейнер?

Вот мой код, в котором я пытаюсь это сделать (на самом деле это заглушка, показывающая, что происходит на стороне пользовательского интерфейса (просмотра)):

public class Test extends JFrame {
    public static ButtonGroup radioButtons = new ButtonGroup();

    public Test() {
        super("Test");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(200, 300);

        final JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        JButton addButton = new JButton("Add");
        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panel.add(new PanelWithRadioButton("text1", "text2"));
                panel.revalidate();
            }
        });
        panel.add(addButton);

        JButton infoButton = new JButton("Info");
        infoButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                for(Enumeration<AbstractButton> myRadioButtons = radioButtons.getElements();
                    myRadioButtons.hasMoreElements();) {
                    JRadioButton btn = (JRadioButton) myRadioButtons.nextElement();

                    if(btn.isSelected()) {
                        PanelWithTwoLabels panelWithLabels = (PanelWithTwoLabels) btn.getComponent(1); //Trying to get Component bind to selected JRadioButton
                        JOptionPane.showMessageDialog(null, "Text1: " + panelWithLabels.getLabel1Text() + ", Text2: " + panelWithLabels.getLabel2Text());
                    }
                }
            }
        });
        panel.add(infoButton);

        getContentPane().add(panel);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Test();
    }

    //JRadioButton + Panel with two text fields
    private class PanelWithRadioButton extends JPanel {
        private JRadioButton rButton;
        private PanelWithTwoLabels panelWithTwoLabels;

        public PanelWithRadioButton(String text1, String text2) {
            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
            panelWithTwoLabels = new PanelWithTwoLabels(text1, text2);
            rButton = new JRadioButton();
            rButton.add(panelWithTwoLabels); //Bind Component to JRadioButton
            radioButtons.add(rButton);

            add(rButton);
            add(panelWithTwoLabels);
        }
    }

    private class PanelWithTwoLabels extends JPanel {
        private JLabel label1;
        private JLabel label2;

        public PanelWithTwoLabels(String text1, String text2) {
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            label1 = new JLabel(text1);
            label2 = new JLabel(text2);

            add(label1);
            add(label2);
        }

        private String getLabel1Text() {
            return label1.getText();
        }

        private String getLabel2Text() {
            return label2.getText();
        }
    }
}

person Dragon    schedule 19.08.2013    source источник


Ответы (2)


Похоже, вы работаете над программой вопросов и ответов, основанной на данных. Хотя показанный подход технически возможен за счет рекурсивного обхода массива, возвращаемого методом контейнера getComponents(), в результате путаются иерархии включения и наследования; он также плохо масштабируется.

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

Приложение: Хотя я не хочу поддерживать неявное ограничение дизайна, вот целесообразный подход.

В PanelWithRadioButton добавьте ссылку на panelWithTwoLabels в качестве свойства клиента:

rButton.putClientProperty("labels", panelWithTwoLabels);

В actionPerformed() используйте свойство для получения panelWithTwoLabels:

PanelWithTwoLabels panelWithLabels =
    (PanelWithTwoLabels) btn.getClientProperty("labels");
person trashgod    schedule 19.08.2013
comment
Я решил перефразировать свой вопрос: то, что описано в примере, это просто пример того, как это будет работать (назовем это заглушкой). Данные, взятые из модели, отображаются в виде переключателя и панели с 2 метками (заполненными данными из модели). И что именно я хочу понять, как получить данные из этих меток, когда я выбираю конкретный переключатель в группе кнопок. Я могу получить выбранный переключатель с помощью модели группы кнопок, но как привязать компонент к выбранному переключателю. Надеюсь, теперь это звучит более подробно :) - person Dragon; 23.08.2013
comment
Я изложил подход выше. - person trashgod; 23.08.2013
comment
Да, я уже пришел к решению. Я храню записи в виде списка в модели. Так что я setAction к каждой радиокнопке как индекс записи из модели. Поэтому, когда я выбираю радиокнопку, я получаю ее ActionCommand и с ее помощью я могу получить именно ту запись, которая мне нужна от модели :) - person Dragon; 23.08.2013

Не относится к вашему вопросу, но...

panel.updateUI();

Не используйте метод updateUI() таким образом. Метод updateUI() используется внутри Swing при изменении LAF.

Когда вы добавляете компоненты в видимый графический интерфейс, вы должны использовать:

panel.revalidat();
panel.repaint(); // sometimes needed
person camickr    schedule 19.08.2013
comment
Ой ну спасибо. Просто у меня был случай, когда перерисовка не работала у меня, когда работало updateUI(). - person Dragon; 20.08.2013