Search code examples
javaswingjbuttonjscrollpane

Adding unknown number of JButton to a JScrollPane


I've look (almost) everywhere(here and here specifically) to find an answer on my problem. I'm trying to add an unknown number of JButton to a JScrollPane depending of the selection of a JComboBox. What I know is you have to add the element to a JPanel in order to get them in your GUI.

Here's an example code : (It does'nt work), it is an example)

public class test {

ArrayList<JButton> button = new ArrayList<JButton>();
String[] stringArray = {"Goat", "Cow", "Dog", "Cat", "Human"};
JComboBox comboBox = new JComboBox(stringArray);
JPanel containerPanel = new JPanel();
JScrollPane scroller = new JScrollPane(containerPanel);

public void addButton(String btnName) {
    button.add(new JButton(btnName));
    containerPanel.add(button.get(button.size() - 1));
}

public class Action implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        addButton(comboBox.getSelectedItem().toString());
    }
}

}

I want to add as many JButton as the user want.

If i just add them like this :

containerPanel.add(new JButton("test"));

It works, but that's not what i want to achieve.

Can you help me?

EDIT: ___________________________________________________________________________

Here is some code that compile and is a simplified replica of what i'm trying to do :

public class Frame extends JFrame {

String[] list = {"Human", "Goat", "Dog", "Cat", "Duck"};
ArrayList<JButton> button = new ArrayList<JButton>();
JComboBox cBox = new JComboBox(list);
JPanel container = new JPanel();
JScrollPane scroller = new JScrollPane(container);

public Frame() {
    cBox.addActionListener(new Action());
    this.setLayout(new BorderLayout());
    this.setSize(200, 200);
    this.add(cBox, BorderLayout.SOUTH);
    this.add(scroller, BorderLayout.CENTER);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setVisible(true);      
}

public void createBtn(String s) {
    System.out.println("Button's label : " + s);
    button.add(new JButton(s));
    System.out.println("Button's index : " + (button.size() - 1));
    container.add(button.get(button.size() - 1));
}

public class Action implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Action made");
        JComboBox temp = (JComboBox) e.getSource();
        createBtn(temp.getSelectedItem().toString());
    }
}
}

Solution

  • So i just discored a very neat function that refresh a JPanel : validate(). It was hiding almost right here in StackOverflow here.

    After some reading about the difference between validate() , revalidate() and invalidate()(That is not useful) here, I decided that validate() is the one i needed.

    Just by adding this function in createBtn(String s) i was able to make all my JButton appear.

    The new code look like this :

    public class Frame extends JFrame {
    
        String[] list = {"Human", "Goat", "Dog", "Cat", "Duck"};
        ArrayList<JButton> button = new ArrayList<JButton>();
        JComboBox cBox = new JComboBox(list);
        JPanel container = new JPanel();
        JScrollPane scroller = new JScrollPane(container);
    
        public Frame() {
            cBox.addActionListener(new Action());
            this.setLayout(new BorderLayout());
            this.setSize(200, 200);
            this.add(cBox, BorderLayout.SOUTH);
            this.add(scroller, BorderLayout.CENTER);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setVisible(true);      
        }
    
        public void createBtn(String s) {
            System.out.println("Button's label : " + s);
            button.add(new JButton(s));
            System.out.println("Button's index : " + (button.size() - 1));
            container.add(button.get(button.size() - 1));
    
            //Note the new addition
            container.validate();
        }
    
        public class Action implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Action made");
                JComboBox temp = (JComboBox) e.getSource();
                createBtn(temp.getSelectedItem().toString());
            }
        }
    }
    

    From what i understood, validate() ask all the child their size and stuff like that and validate that they are ok to proceed. The only problem is that can it be time consuming. In other word, it can cause performance issue.

    Correct me if you got a better answer.