0

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());
    }
}
}
Community
  • 1
  • 1
Chax
  • 1,041
  • 2
  • 14
  • 36
  • You list [this question](http://stackoverflow.com/questions/22268958/how-to-add-jbutton-on-jscrollpane), and yet you inexplicably ignore the answer to use a suitable layout such as a GridLayout -- why? Why not set the containerPanel's layout to be GridLayout and add your buttons to this? – Hovercraft Full Of Eels Feb 01 '15 at 14:51
  • 1
    Ehm just use a loop to add as many buttons as you want? – Murat Karagöz Feb 01 '15 at 14:53
  • @HovercraftFullOfEels I've tried to use a `BoxLayout` and also a `FlowLayout`, but none works. – Chax Feb 01 '15 at 14:57
  • @MuratK. The problem is that I don't know how many button there will be – Chax Feb 01 '15 at 14:58
  • 1
    Chax: don't believe it unless I see it -- so show us. For my money, I'd use a GridLayout, I'd add my buttons in a for loop in the listener attached to the JComboBox. I'd call revalidate and repaint on my button's container after adding, and I"d be done. And yes you **do** know how many buttons there will be. The Comb box will tell you how many items are selected! – Hovercraft Full Of Eels Feb 01 '15 at 14:58
  • You said you want to use a Combobox. With that you know how many you need. – Murat Karagöz Feb 01 '15 at 14:59
  • @HovercraftFullOfEels I really don't see how to put a loop in there because i want the button to be shown directly after it have been selected in the `JComboBox`, not after it all been all selected(that I would be able to do it). – Chax Feb 01 '15 at 15:14
  • Then you don't need a for loop. You just need to create and add your JButton to the containerPanel in your JComboBox's ActionListener. – Hovercraft Full Of Eels Feb 01 '15 at 15:16
  • Like I did in my example code? If so, there is something i don't quite get then. – Chax Feb 01 '15 at 15:22
  • I don't see where you've added an ActionListener to your JComboBox. You've created an ActionListener class, yes, but your posted code does not show you adding it to anything. – Hovercraft Full Of Eels Feb 01 '15 at 15:25
  • @HovercraftFullOfEels Let me work some code out and i'll edit my post when i'll be home. – Chax Feb 01 '15 at 15:27
  • Please do so and good luck. – Hovercraft Full Of Eels Feb 01 '15 at 15:29
  • @HovercraftFullOfEels there you go. I updated my post. This code is an almost exact replica of my actual code. I figured out what you meant by loop and if i got it right it should be there. Still there is nothing that appear. The `System` call output exactly what i want tough it isn't still visible. – Chax Feb 01 '15 at 23:37

1 Answers1

1

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.

Community
  • 1
  • 1
Chax
  • 1,041
  • 2
  • 14
  • 36