java expandable JDialog

1k views Asked by At

For my application I have a JDialog which contains a JPanel with some basic JTextFields and JButtons. The idea is to have a button which expands the JDialog to reveal a second JPanel which contains some "advance" settings.

I have achieved this with calling setPreferredSize() and pack(), but this isn't very elegant. An "elegant" solution would be to set the second Panel to be somehow null and therefore to get ignored by pack() when the toggle state is in "retracted".

Sorry that I can't provide you with code (that thing is about 700 lies) but all it is like I said basically two JPanels in a JDialog.

Here some pics:

enter image description hereenter image description here

Question: is there a trick to get this expanding thing going without having to set fixed dimensions for the expanded/normal state.

1

There are 1 answers

8
MadProgrammer On BEST ANSWER

There are probably a few ways you could do this, you could, for example, simply add and remove the bottom panel as needed. If I can, I'd like to avoid this, as it can make managing the layout more difficult.

Another solution is simply to make the component visible/invisible, but you need to find a layout manager which will actually treat a invisible component like it's not there (0x0) - and yes, I had issues with a couple while putting a test together...

Flip

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FlipDialog {

    public static void main(String[] args) {
        new FlipDialog();
    }

    public FlipDialog() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JButton flip;
        private JPanel bottom;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(8, 8, 8, 8);
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            JPanel top = new JPanel();
            flip = new JButton("+");
            top.add(flip);
            add(top, gbc);

            bottom = new JPanel();
            bottom.add(new JLabel("Boo"));
            bottom.setVisible(false);

            add(bottom, gbc);

            flip.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    bottom.setVisible(!bottom.isVisible());
                    if (bottom.isVisible()) {
                        flip.setText("-");
                    } else {
                        flip.setText("+");
                    }
                    revalidate();
                    Window window = SwingUtilities.windowForComponent(bottom);
                    window.pack();
                }
            });
        }

    }

}

It should be noted that the call to revalidate is probably irrelevant as you're packing the window anyway

Updated with layout example

ClosedOpended

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractSpinnerModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class Test100 {

    public static void main(String[] args) {
        new Test100();
    }

    public Test100() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new SearchPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class SearchPane extends JPanel {

        private ObjectsPane objectsPane;
        private AdvanceSettingsPane advanceSettingsPane;

        public SearchPane() {
            setBorder(new EmptyBorder(8, 8, 8, 8));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;

            objectsPane = new ObjectsPane();
            add(objectsPane, gbc);

            gbc.gridy++;
            gbc.weighty = 0;

            advanceSettingsPane = new AdvanceSettingsPane();
            advanceSettingsPane.setVisible(false);
            add(advanceSettingsPane, gbc);

            objectsPane.addExpandCollapseListener(new ChangeListener() {

                @Override
                public void stateChanged(ChangeEvent e) {
                    System.out.println(objectsPane.isExpanded());
                    advanceSettingsPane.setVisible(objectsPane.isExpanded());
                    Window window = SwingUtilities.windowForComponent(SearchPane.this);
                    window.pack();
                }
            });
        }

        public class ObjectsPane extends JPanel {

            private JSpinner findField;
            private JTextField replaceField;

            private JButton expandButton;
            private JButton replaceButton;
            private JButton replaceAllButton;

            private boolean expanded = false;

            public ObjectsPane() {
                setLayout(new GridBagLayout());

                findField = new JSpinner(new AbstractSpinnerModel() {

                    @Override
                    public Object getValue() {
                        return "";
                    }

                    @Override
                    public void setValue(Object value) {
                    }

                    @Override
                    public Object getNextValue() {
                        return "";
                    }

                    @Override
                    public Object getPreviousValue() {
                        return "";
                    }
                });
                replaceField = new JTextField(10);

                replaceButton = new JButton("Replace");
                replaceAllButton = new JButton("Replace All");
                expandButton = new JButton("+");

                GridBagConstraints gbc = new GridBagConstraints();
                gbc.insets = new Insets(4, 4, 4, 4);
                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                gbc.weightx = 1;
                gbc.anchor = GridBagConstraints.WEST;
                add(new JLabel("Objects found:"), gbc);

                gbc.gridx = 0;
                gbc.gridy = 1;
                gbc.gridwidth = 1;
                gbc.weightx = 0;
                add(new JLabel("Find:"), gbc);

                gbc.gridy = 2;
                add(new JLabel("Replace:"), gbc);

                gbc.gridx = 1;
                gbc.gridy = 1;
                gbc.weightx = 1;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                add(findField, gbc);

                gbc.gridy = 2;
                add(replaceField, gbc);

                gbc.anchor = GridBagConstraints.WEST;
                gbc.gridwidth = 1;
                gbc.weightx = 0;
                gbc.gridx = 0;
                gbc.gridy = 3;
                gbc.fill = GridBagConstraints.NONE;
                add(expandButton, gbc);

                JPanel pnlButtons = new JPanel(new GridLayout(1, 2));
                pnlButtons.add(replaceButton);
                pnlButtons.add(replaceAllButton);

                gbc.gridx = 1;
                gbc.gridy = 3;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                gbc.weightx = 1;
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                add(pnlButtons, gbc);

                expandButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        expanded = !expanded;
                        if (expanded) {
                            expandButton.setText("-");
                        } else {
                            expandButton.setText("+");
                        }
                        fireStateChanged();
                    }
                });
            }

            public boolean isExpanded() {
                return expanded;
            }

            public void addExpandCollapseListener(ChangeListener listener) {
                listenerList.add(ChangeListener.class, listener);
            }

            public void removeExpandCollapseListener(ChangeListener listener) {
                listenerList.remove(ChangeListener.class, listener);
            }

            protected void fireStateChanged() {
                ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
                if (listeners.length > 0) {

                    ChangeEvent evt = new ChangeEvent(this);
                    for (ChangeListener listener : listeners) {
                        listener.stateChanged(evt);
                    }

                }
            }

        }

        public class AdvanceSettingsPane extends JPanel {

            public AdvanceSettingsPane() {
                setBorder(new TitledBorder("Advance Settings"));
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
//              gbc.gridy = 0;
                gbc.weightx = 1;
                gbc.anchor = GridBagConstraints.WEST;
                gbc.gridwidth = GridBagConstraints.REMAINDER;

                add(new JCheckBox("Live Update"), gbc);
                add(new JCheckBox("Word search"), gbc);
                add(new JCheckBox("Ignore Case"), gbc);
            }

        }

    }

}