Home > Enterprise >  Dynamic resizing of JMenu after adding items at runtime
Dynamic resizing of JMenu after adding items at runtime

Time:09-17

As in title, I struggle to get my JMenu to resize when programatically adding components. In my application I need JMenu with JCheckBoxes. Whenever I tick one of them, JSlider should appear just below. Below is the code that makes that happen. The problem I have is that when there's lot of sliders visible, items in JMenu get clumped - see image below.

How can I force redraw/resize/expansion of JMenu to perserve original checkboxes/sliders height?

Also note - JMenu stays visible at all times when selecting checkboxes. It closes only when I click outside of it. But after such 'restart' menu grows and problem is no longer present.

Many thanks in advance!

public class Window extends JFrame implements ActionListener {
    private JPanel panel;
    private JMenuBar menuBar;
    private JMenu menu;
    private JSlider slider1;
    private JCheckBoxMenuItem checkBox1;
    private JCheckBoxMenuItem checkBox2;
    private JCheckBoxMenuItem checkBox3;

    public Window() {
        super("Example");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(300,300));

        panel = new JPanel();
        panel.setMinimumSize(new Dimension(300,300));

        menuBar = new JMenuBar();
        menu = new JMenu("Options");

        checkBox1 = new JCheckBoxMenuItem("option 1");
        checkBox2 = new JCheckBoxMenuItem("option 2");
        checkBox3 = new JCheckBoxMenuItem("option 3");

        checkBox1.addActionListener(this);
        //prevent JMenu from closing after selecting CheckBox
        checkBox1.setUI(new BasicCheckBoxMenuItemUI() {
            @Override
            protected void doClick(MenuSelectionManager msm) {
                checkBox1.doClick(0);
            }
        });

        slider1 = new JSlider();
        slider1.setVisible(false);

        menu.add(checkBox1);
        menu.add(slider1);
        menu.add(checkBox2);
        menu.add(checkBox3);
        menuBar.add(menu);
        setJMenuBar(menuBar);
        add(panel);
        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(checkBox1)) {
            slider1.setVisible(checkBox1.isSelected());
        }
    }
}

Here's screen from my main application:

Clumped items

CodePudding user response:

Call revalidate() it is supposed to do the trick, call it on the newly added components. https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Component.html#revalidate()

But i would say a use case like this is not what menus are meant for? why not use a dialog for dynamic components?

For background https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Component.html#revalidate() call it o the newly added component and see https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Component.html#invalidate() and https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Container.html#isValidateRoot()

CodePudding user response:

Hiding and reshowing the popup menu will cause it to be resized:

@Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource().equals(checkBox1)) {
        slider1.setVisible(checkBox1.isSelected());
        menu.setPopupMenuVisible(false);
        menu.setPopupMenuVisible(true);
    }
}
  • Related