SetVisible(false) changes the layout of my compone

2020-07-11 04:46发布

How do I make the subpanels within my main panel stay where they are when I set one of the subpanels to be invisible?

What I have looks like:

[ (Panel1) (Panel2) (Panel3) (Panel4) ]

When I do panel3.setVisible(false) it then looks like:

[      (Panel1) (Panel2) (Panel4)     ]

I would like it to look like:

[ (Panel1) (Panel2)          (Panel4) ]

I am using the GridBagLayout and my mainPanel declaration looks like:

final JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

and I add an new panel like:

final JTextField valueTextField = new JTextField();
valueTextField.setPreferredSize(new Dimension(80, 25));
valueTextField.setName("Value");
c.gridx =0;
panel.add(valueTextField, c);

I'll provide more code if needed and I don't care which layout I use as long as it gets me what I want.

3条回答
Summer. ? 凉城
2楼-- · 2020-07-11 05:00

I believe all the layout manager respect the visibility of a component and don't include invisible components in the preferred size and layout calculations.

One solution might be to wrap all your panels in a panel using the OverlayLayout:

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

public class OverlayLayoutInvisible
{
    public static void main(String[] args)
    {
        JPanel panel = new JPanel();
        panel.add( createPanel("Button 1") );
        panel.add( createPanel("Button 2") );
        panel.add( createPanel("Button 3") );
        panel.add( createPanel("Button 4") );
        panel.add( createPanel("Button 5") );

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

    public static JPanel createPanel(String text)
    {
        JButton button = new JButton( text );
        button.addActionListener( new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                Component c = (Component)e.getSource();
                c.setVisible(false);
            }
        });

        InvisibleComponent ic = new InvisibleComponent( button );

        JPanel panel = new JPanel();
        panel.setLayout( new OverlayLayout(panel) );
        panel.add( ic );
        panel.add( button );


        return panel;
    }

    public static class InvisibleComponent extends JComponent
    {
        private Component master;

        public InvisibleComponent(Component master)
        {
            this.master = master;
            setAlignmentX( master.getAlignmentX() );
            setAlignmentY( master.getAlignmentY() );
        }

        public Dimension getPreferredSize()
        {
            return master.getPreferredSize();
        }
    }
}
查看更多
姐就是有狂的资本
3楼-- · 2020-07-11 05:09

I suggest using a CardLayout within the individual cells, and instead of setting it to invisible, switch to an empty panel instead.

The code below demonstrates this. Within hidePanel() there are two options to hide the cell with the CardLayout route currently enabled.

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

public class InvisiblePanels {
    public static void main(String... args) throws Exception {
        JFrame frame = new JFrame();
        frame.setLayout(new GridBagLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        frame.add(new MyPanel(), c);
        c.gridx = 1;
        frame.add(new MyPanel(), c);
        c.gridx = 2;
        frame.add(new MyPanel(), c);

        frame.pack();
        frame.setVisible(true);

    }

    private static class MyPanel extends JPanel {

        CardLayout layout;

        public MyPanel() {
            layout = new CardLayout();
            setLayout(layout);
            JButton button = new JButton("Click me");
            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    hidePanel();
                }
            });
            add(button, "visible");
            add(new JPanel(), "invisible");
            layout.show(this, "visible");
        }

        public void hidePanel() {
//            setVisible(false);
            layout.show(this, "invisible");
        }
    }
}
查看更多
【Aperson】
4楼-- · 2020-07-11 05:19

You might be able to tweak GridLayout (do you have an SSCCE?)

Otherwise:

Put Panel3 and Panel4 together in a single panel that you add to the GridBagLayout. Then setup the new Panel in a Layout like FlowLayout (aligned Left with a preferred size), BorderLayout, GridLayout, etc.

查看更多
登录 后发表回答