SetVisible(false) изменяет макет моих компонентов в моей панели

Как сделать так, чтобы подпанели на моей главной панели оставались там, где они есть, когда я делаю одну из подпанелей невидимой?

То, что у меня есть, выглядит так:

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

Когда я делаю panel3.setVisible(false), это выглядит так:

[      (Panel1) (Panel2) (Panel4)     ]

Я хотел бы, чтобы это выглядело так:

[ (Panel1) (Panel2)          (Panel4) ]

Я использую GridBagLayout, и мое объявление mainPanel выглядит так:

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

и я добавляю новую панель, например:

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

Я предоставлю больше кода, если это необходимо, и мне все равно, какой макет я использую, пока он дает мне то, что я хочу.


person Grammin    schedule 26.05.2011    source источник


Ответы (3)


Я предлагаю использовать CardLayout внутри отдельных ячеек и вместо установив его на невидимый, вместо этого переключитесь на пустую панель.

Код ниже демонстрирует это. В hidePanel() есть два варианта скрыть ячейку с включенным маршрутом CardLayout.

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");
        }
    }
}
person Mark Peters    schedule 26.05.2011

Я считаю, что все менеджеры компоновки уважают видимость компонента и не включают невидимые компоненты в расчеты предпочтительного размера и компоновки.

Одним из решений может быть объединение всех ваших панелей в панель с помощью 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();
        }
    }
}
person camickr    schedule 26.05.2011
comment
Обратите внимание, что комментарий о видимости всего макета верен лишь частично. У некоторых макетов есть варианты поведения в этом случае (у MigLayout есть, и я думаю, что у GroupLayout тоже). DesignGridLayout не заботится о видимости компонентов: добавленные компоненты располагаются одинаково, независимо от того, видны они или нет. - person jfpoilpret; 27.05.2011
comment
+1 Цвет меня ошарашил. Я думал, что вы имеете в виду пользовательский макет, пока я не проверил JavaDocs! Документы. немного тонкие с тегами @since, когда это было введено? - person Andrew Thompson; 27.05.2011
comment
@ Эндрю Томпсон, сколько я себя помню, он был там, но я никогда не находил его таким полезным. Кажется, я помню, что у меня были проблемы с пониманием того, как он позиционирует компоненты на панели, когда они имеют разные размеры. Кроме того, вы должны быть осторожны с наложением компонентов. Например, если вы поместите метку поверх кнопки. Кнопка будет рисовать поверх метки при наведении курсора мыши, так как кнопка получает событие наведения мыши и рисует эффект ролловера для кнопки. - person camickr; 27.05.2011
comment
Спасибо. С тех пор я заметил, что учебник по Java, похоже, не охватывает его. Возможно, разработчики Swing немного смущены OverlayLayout (что постоянно напоминает мне Beck — рифмуется с Odelay). ;) - person Andrew Thompson; 27.05.2011

Возможно, вы сможете настроить GridLayout (у вас есть SSCCE?)

Иначе:

Объедините Panel3 и Panel4 в одну панель, которую вы добавите в GridBagLayout. Затем настройте новую панель в макете, таком как FlowLayout (выровненный по левому краю с предпочтительным размером), BorderLayout, GridLayout и т. д.

person jzd    schedule 26.05.2011