3
votes

I am trying to dynamically generate a form. Basically, I want to load a list of items for purchase, and generate a button for each. I can confirm that the buttons are being generated with the debugger, but they aren't being displayed. This is inside a subclass of JPanel:

private void generate() {
    JButton b = new JButton("height test");
    int btnHeight = b.getPreferredSize().height;
    int pnlHeight = this.getPreferredSize().height;
    int numButtons = pnlHeight / btnHeight;

    setLayout(new GridLayout(numButtons, 1));

    Iterator<Drink> it = DrinkMenu.iterator();

    for (int i = 0; i <= numButtons; ++i) {
        if (!it.hasNext()) {
            break;
        }
        final Drink dr = it.next();
        b = new DrinkButton(dr);
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                order.addDrink(dr);
        }});
        add(b);
    }
    revalidate();
}

DrinkButton is a subclass of JButton. Any ideas?

3
Why are you setting b to a JButton then lower down setting it again to DrinkButtonRMT
make sure that these modifications are happening in the Event Dispatch Threadmre
The basic code looks fine. You are using revalidate() which is a key. But we don't know the context of how this code is being used. We don't if this panel has actually been added to the frame. Post your SSCCE (sscce.org) that demonstrates the problem.camickr

3 Answers

4
votes

example about validate() revalidate() plus repaint(), look like as required for correct output to the GUI, layed by some of LayourManagers

EDIT: as trashgod noticed, I added Schedule a job for the EDT

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;

    public class ValidateRevalidateRepaint {

        private JPanel panel;
        private GridBagConstraints gbc;
        private boolean validate, revalidate, repaint;

        public ValidateRevalidateRepaint() {
            validate = revalidate = repaint = false;
            panel = new JPanel(new GridBagLayout());
            gbc = new GridBagConstraints();
            gbc.insets = new Insets(0, 20, 0, 20);
            panel.add(getFiller(), gbc);
            JFrame f = new JFrame();
            f.setJMenuBar(getMenuBar());
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(panel);
            f.getContentPane().add(getRadioPanel(), "East");
            f.getContentPane().add(getCheckBoxPanel(), "South");
            f.setSize(400, 200);
            f.setLocation(200, 200);
            f.setVisible(true);
        }

        private JMenuBar getMenuBar() {
            JMenu menu = new JMenu("change");
            ActionListener l = new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    JMenuItem item = (JMenuItem) e.getSource();
                    int n = Integer.parseInt(item.getActionCommand());
                    makeChange(n);
                }
            };
            for (int j = 1; j < 5; j++) {
                String s = String.valueOf(j) + " component";
                if (j > 1) {
                    s += "s";
                }
                JMenuItem item = new JMenuItem(s);
                item.setActionCommand(String.valueOf(j));
                item.addActionListener(l);
                menu.add(item);
            }
            JMenuBar menuBar = new JMenuBar();
            menuBar.add(menu);
            return menuBar;
        }

        private JPanel getRadioPanel() {
            JPanel panel1 = new JPanel(new GridBagLayout());
            GridBagConstraints gbc1 = new GridBagConstraints();
            gbc1.insets = new Insets(2, 2, 2, 2);
            gbc1.weighty = 1.0;
            gbc1.gridwidth = GridBagConstraints.REMAINDER;
            ButtonGroup group = new ButtonGroup();
            ActionListener l = new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    JRadioButton radio = (JRadioButton) e.getSource();
                    int n = Integer.parseInt(radio.getActionCommand());
                    makeChange(n);
                }
            };
            for (int j = 0; j < 4; j++) {
                String s = String.valueOf(j + 1);
                JRadioButton radio = new JRadioButton(s);
                radio.setActionCommand(s);
                radio.addActionListener(l);
                group.add(radio);
                panel1.add(radio, gbc1);
            }
            return panel1;
        }

        private JPanel getCheckBoxPanel() {
            final String[] operations = {"validate", "revalidate", "repaint"};
            ActionListener l = new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    JCheckBox checkBox = (JCheckBox) e.getSource();
                    String ac = checkBox.getActionCommand();
                    boolean state = checkBox.isSelected();
                    if (ac.equals("validate")) {
                        validate = state;
                    }
                    if (ac.equals("revalidate")) {
                        revalidate = state;
                    }
                    if (ac.equals("repaint")) {
                        repaint = state;
                    }
                }
            };
            JPanel panel2 = new JPanel();
            for (int j = 0; j < operations.length; j++) {
                JCheckBox check = new JCheckBox(operations[j]);
                check.setActionCommand(operations[j]);
                check.addActionListener(l);
                panel2.add(check);
            }
            return panel2;
        }

        private void makeChange(int number) {
            panel.removeAll();
            for (int j = 0; j < number; j++) {
                panel.add(getFiller(), gbc);
            }
            if (validate) {
                panel.validate();
            }
            if (revalidate) {
                panel.revalidate();
            }
            if (repaint) {
                panel.repaint();
            }
        }

        private JPanel getFiller() {
            JPanel panel3 = new JPanel();
            panel3.setBackground(Color.red);
            panel3.setPreferredSize(new Dimension(40, 40));
            return panel3;
        }

        public static void main(String[] args) {//added Schedule a job for the EDT
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ValidateRevalidateRepaint rVR = new ValidateRevalidateRepaint();
            }
        });
    }
}
3
votes

Works on my computer...

public class Panel extends JPanel {

    public Panel() {
        setLayout(new java.awt.GridLayout(4, 4));
        for (int i = 0; i < 16; ++i) {
            JButton b = new JButton(String.valueOf(i));
            b.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    //...
                }
            });
            add(b);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run(){
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(new Dimension(300, 300));
                frame.add(new Panel());
                frame.setVisible(true);
            }
        });
    }
}

As far as I remember your version was working as well, although I had to remove your "drinking" code. Start from this example (it shows nice 4x4 grid of buttons) and determine what is wrong with your code.

3
votes

You can use revalidate(), as shown in this example.

Addendum: Here's my variation on @mKorbel's interesting answer that shows a similar result for GridLayout. It looks like repaint() may be necessary after revalidate().

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/** @see https://stackguides.com/questions/6395105 */
public class ValidateRevalidateRepaint {

    private JPanel center;
    private boolean validate = false;
    private boolean revalidate = true;
    private boolean repaint = true;

    public ValidateRevalidateRepaint() {
        center = new JPanel(new GridLayout(1, 0, 10, 10));
        JFrame f = new JFrame();
        f.setTitle("VRR");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(center, BorderLayout.CENTER);
        f.add(getRadioPanel(), BorderLayout.EAST);
        f.add(getCheckBoxPanel(), BorderLayout.SOUTH);
        makeChange(4);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private JPanel getRadioPanel() {
        JPanel panel = new JPanel(new GridLayout(0, 1));
        ButtonGroup group = new ButtonGroup();
        ActionListener l = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JRadioButton radio = (JRadioButton) e.getSource();
                int n = Integer.parseInt(radio.getActionCommand());
                makeChange(n);
            }
        };
        for (int j = 0; j < 4; j++) {
            String s = String.valueOf(j + 1);
            JRadioButton radio = new JRadioButton(s);
            radio.setActionCommand(s);
            radio.addActionListener(l);
            group.add(radio);
            panel.add(radio);
            if (j == 3) {
                group.setSelected(radio.getModel(), true);
            }
        }
        return panel;
    }

    private JPanel getCheckBoxPanel() {
        final String[] operations = {"validate", "revalidate", "repaint"};
        ActionListener l = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JCheckBox checkBox = (JCheckBox) e.getSource();
                String ac = checkBox.getActionCommand();
                boolean state = checkBox.isSelected();
                if (ac.equals("validate")) {
                    validate = state;
                }
                if (ac.equals("revalidate")) {
                    revalidate = state;
                }
                if (ac.equals("repaint")) {
                    repaint = state;
                }
            }
        };
        JPanel panel = new JPanel();
        for (int j = 0; j < operations.length; j++) {
            JCheckBox check = new JCheckBox(operations[j]);
            if (j == 0) {
                check.setSelected(false);
            } else {
                check.setSelected(true);
            }
            check.setActionCommand(operations[j]);
            check.addActionListener(l);
            panel.add(check);
        }
        return panel;
    }

    private void makeChange(int number) {
        center.removeAll();
        for (int j = 0; j < number; j++) {
            center.add(getFiller());
        }
        if (validate) {
            center.validate();
        }
        if (revalidate) {
            center.revalidate();
        }
        if (repaint) {
            center.repaint();
        }
    }

    private JPanel getFiller() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createLineBorder(Color.blue, 5));
        panel.setBackground(Color.red);
        panel.setPreferredSize(new Dimension(50, 50));
        return panel;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ValidateRevalidateRepaint();
            }
        });
    }
}