1

I have a bunch of dynamically added panels that contain radio button and a panel with several labels bind to radio button. Suppose I have a button that should retrieve container with labels bind to selected radio button or let's say another words - data bind to selected radio button. But how to get this container?

Here is my code where I try to do this (in fact this is a stub to show what is going on on UI (view) side):

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();
        }
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Dragon
  • 2,431
  • 11
  • 42
  • 68

2 Answers2

4

It sounds like you're working on a data driven Q&A program. While the approach shown is technically possible by recursively traversing the array returned from the container's getComponents() method, the result confuses the containment & inheritance hierarchies; it also scales poorly.

Instead, separate the model (strings, selection) and view (labels, buttons), as suggested here. Let the view listen to its model using one of the notification approaches shown. In this way, each instance of the view knows its own buttons and which button is selected. Almost any of the standard Swing components is a good example of this separable model architecture.

Addendum: While I'm reluctant to endorse the implicit design limitation, here's an expedient approach.

In PanelWithRadioButton, add a reference to panelWithTwoLabels as a client property:

rButton.putClientProperty("labels", panelWithTwoLabels);

In actionPerformed(), use the property to retrieve the panelWithTwoLabels:

PanelWithTwoLabels panelWithLabels =
    (PanelWithTwoLabels) btn.getClientProperty("labels");
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I decided to rephrase my question: what is described in example is just example of how it is going to work (let's call it a stub). Data taken from a model is put to the view as a radio button and panel with 2 labels (filled with data from model). And what exactly I want to understand, how to get data from these labels when I select specific radio button in button group. I can get selected radio button via button group model, but how to get component bind to selected radio button. Hope now it sounds more detailed :) – Dragon Aug 23 '13 at 09:23
  • I've outlined an approach above. – trashgod Aug 23 '13 at 10:59
  • 1
    Yes, I've already come to a solution. I keep records as a List in a model. So I `setAction` to each radiobutton as index of a record from model. So when I select radiobutton, I receive its `ActionCommand` and with it I can get exact record I need from a model :) – Dragon Aug 23 '13 at 11:34
2

Not related to your question but...

panel.updateUI();

Don't use the updateUI() method that way. The updateUI() method is used internally by Swing when the LAF is changed.

When you add components to a visible GUI you should use:

panel.revalidat();
panel.repaint(); // sometimes needed
camickr
  • 321,443
  • 19
  • 166
  • 288