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 се промени.

Когато добавяте компоненти към видим GUI, трябва да използвате:

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