Swing:添加尺寸等于0的隐藏JPanel在转向可见时不会重新计算

时间:2014-09-05 11:32:55

标签: java swing jpanel layout-manager repaint

我有这个程序,有两个面板,一个在左边有2个切换按钮,另一个在右边显示一个标签。
选中后,每个按钮都会在右侧区域添加其面板(并设置另一个不可见) 取消选择后,将其删除 在最后一种情况下,我希望其他面板(如果添加到容器中)变为可见。

代码基本上有效,但是如果在开始面板1中取消选择第二个按钮则没有出现 我发现面板1的尺寸设置为0,如果我手动设置此尺寸,则会出现面板。不幸的是,通过这样做,布局管理器停止处理面板尺寸(当我调整窗口或JSplitPanel的大小时,这很糟糕!)。

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

        @Override
        public void run() {
            final JFrame frame = new JFrame();
            frame.setSize(800, 800);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            final JPanel buttonsPanel = new JPanel(new FlowLayout());
            final JToggleButton btn1 = new JToggleButton("Button 1");
            final JToggleButton btn2 = new JToggleButton("Button 2");

            buttonsPanel.add(btn1);
            buttonsPanel.add(btn2);

            final JPanel containerPanel = new JPanel(new BorderLayout());
            final JPanel pan1;
            final JPanel pan2;
            pan1 = new JPanel(new BorderLayout());
            pan2 = new JPanel(new BorderLayout());

            pan1.add(new JLabel("panel 1"));
            pan2.add(new JLabel("panel 2"));

            pan1.setBackground(Color.WHITE);
            pan2.setBackground(Color.RED);

            btn1.addItemListener(new ItemListener() {

                @Override
                public void itemStateChanged(final ItemEvent e) {
                    final int state = e.getStateChange();
                    for (final Component component : containerPanel.getComponents()) {
                        component.setVisible(false);
                    }

                    if (state == ItemEvent.SELECTED) {
                        containerPanel.add(pan1, BorderLayout.CENTER);
                        pan1.setVisible(true);
                    }
                    else {
                        containerPanel.remove(pan1);
                        for (final Component component : containerPanel.getComponents()) {
                            component.setVisible(true);
                            break;
                        }
                    }
                    containerPanel.invalidate();
                    containerPanel.repaint();
                }
            });

            btn2.addItemListener(new ItemListener() {

                @Override
                public void itemStateChanged(final ItemEvent e) {
                    final int state = e.getStateChange();
                    for (final Component component : containerPanel.getComponents()) {
                        component.setVisible(false);
                    }

                    if (state == ItemEvent.SELECTED) {
                        pan2.setVisible(true);
                        containerPanel.add(pan2, BorderLayout.CENTER);
                    }
                    else {
                        containerPanel.remove(pan2);
                        for (final Component component : containerPanel.getComponents()) {
                            component.setVisible(true);
                            // component.setSize(containerPanel.getSize());
                            break;
                        }
                    }
                    containerPanel.revalidate();
                    containerPanel.repaint();
                }
            });

            btn1.setSelected(true);
            btn2.setSelected(true);

            final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                                        true,
                                                        buttonsPanel,
                                                        containerPanel);
            splitPane.setResizeWeight(0.5);
            frame.add(splitPane);
            frame.setVisible(true);

        }
    });

}

如果不手动设置其他面板尺寸,如何解决此问题? 我知道CardLayout是这类要求的解决方案,但遗憾的是它并不适用于我的问题。

由于

修改 根据评论中的要求,这里有一个简单的动作序列来解释问题:

我的期望:

  1. 启动应用程序 - >选择了两个按钮,两个面板都添加到右侧容器中,只有面板2可见(因为按钮2是最后一个通过代码选择)。
  2. 取消选择按钮2 - >将面板2从右侧容器中取出,将面板1切换为可见并出现在右侧容器中。
  3. 真正发生的事情:

    1. 与预期相同
    2. 面板1未显示,因为其尺寸均为0,无效且重绘不起作用

1 个答案:

答案 0 :(得分:0)

  

“两个面板都添加到右侧容器中,只有面板2可见”

这是不正确的。您正在使用BorderLayout。问题是每个位置只能有一个组件。第一个被踢出(容器中不再存在),只剩下最后一个,并且你试图将两者都添加到CENTER

所以你假设通过删除第二个面板,当你调用setVisible时第一个面板会自动出现,这是不正确的。实际上需要再次添加组件。

根据这些新信息,尝试调试您的问题。也可以使用revalidate()代替invalidate()

  

“面板1未显示,因为其尺寸均为0”

与此无关。 BorderLayout并不关心大小。它会拉伸面板以适应。


除此之外:这是CardLayout的完美情况。不确定为什么你不能使用它,但也许你应该深入研究实现它的可能性


<强>更新

我想这可能就是你要找的东西。这只是切换其他按钮状态的问题。

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

public class Test {

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

            @Override
            public void run() {
                final JFrame frame = new JFrame();
                frame.setSize(800, 800);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final JPanel buttonsPanel = new JPanel(new FlowLayout());
                final JToggleButton btn1 = new JToggleButton("Button 1");
                final JToggleButton btn2 = new JToggleButton("Button 2");

                buttonsPanel.add(btn1);
                buttonsPanel.add(btn2);

                final JPanel containerPanel = new JPanel(new BorderLayout());
                final JPanel pan1;
                final JPanel pan2;
                pan1 = new JPanel(new BorderLayout());
                pan2 = new JPanel(new BorderLayout());

                pan1.add(new JLabel("panel 1"));
                pan2.add(new JLabel("panel 2"));

                pan1.setBackground(Color.WHITE);
                pan2.setBackground(Color.RED);

                btn1.addItemListener(new ItemListener() {

                    @Override
                    public void itemStateChanged(final ItemEvent e) {
                        final int state = e.getStateChange();

                        if (state == ItemEvent.SELECTED) {
                            containerPanel.add(pan1, BorderLayout.CENTER);
                            containerPanel.remove(pan2);
                            btn2.getModel().setSelected(false);
                        } else {
                            containerPanel.add(pan2, BorderLayout.CENTER);
                            containerPanel.remove(pan1);
                            btn2.getModel().setSelected(true);
                        }
                        containerPanel.revalidate();
                        containerPanel.repaint();
                    }
                });

                btn2.addItemListener(new ItemListener() {

                    @Override
                    public void itemStateChanged(final ItemEvent e) {
                        final int state = e.getStateChange();
                        if (state == ItemEvent.SELECTED) {
                            containerPanel.add(pan2, BorderLayout.CENTER);
                            containerPanel.remove(pan1);
                            btn1.getModel().setSelected(false);
                        } else {
                            containerPanel.add(pan1, BorderLayout.CENTER);
                            containerPanel.remove(pan2);
                            btn1.getModel().setSelected(true);
                        }

                        containerPanel.revalidate();
                        containerPanel.repaint();
                    }
                });

                btn1.setSelected(true);
                btn2.setSelected(true);

                final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                        true,
                        buttonsPanel,
                        containerPanel);
                splitPane.setResizeWeight(0.5);
                frame.add(splitPane);
                frame.setVisible(true);

            }
        });
    }
}