【问题标题】:JavaGUI: Box layout with width fit to container?JavaGUI:宽度适合容器的框布局?
【发布时间】:2014-01-23 20:48:04
【问题描述】:

我正在为具有改进过滤功能的自定义源服务器浏览器制作 GUI。

这就是我拥有的so far

但是,当我resize...

当我调整窗口大小时,我希望 L4D2 的“过滤器面板”调整为容器的当前最大宽度。我还希望能够在一列中添加更多这些面板(例如提供的框布局)。

Boxlayout 让面板出现在一列中,但它对它们的宽度没有任何作用。 我想我可能需要覆盖过滤器面板首选大小方法,以便它们可以检索父容器的大小,但我不知道该怎么做。

我应该如何解决这个问题?

编辑:这是一个描述问题的示例程序。

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

public class guiExampleProblem {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final MyWindows wnd = new MyWindows("guiExampleProblem");
                wnd.setVisible(true);
            }
        });
    }
}

class MyWindows extends JFrame {
    public MyWindows(String text) {
        super(text);

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);        

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));        

        JPanel containerPanel1 = new JPanel();
        JPanel containerPanel2 = new JPanel();
        JPanel containerPanel3 = new JPanel();
        containerPanel1.setBackground(Color.BLACK);
        containerPanel2.setBackground(Color.RED);
        containerPanel3.setBackground(Color.GREEN); 

        mainPanel.add(containerPanel1);
        mainPanel.add(containerPanel2);
        mainPanel.add(containerPanel3);

        this.add(mainPanel);
        pack();
    }   
}

调整窗口大小时,我希望面板仅沿 x 轴展开,并在 y 轴上保持恒定高度,但在示例中,面板同时在 x y 轴上展开。

【问题讨论】:

    标签: java swing user-interface resize width


    【解决方案1】:

    我设法通过覆盖“过滤器面板”的 getPreferedSize 方法来获得所需的功能,以便它们检索父容器的宽度并使用它。下面是示例形式的代码:

    import javax.swing.*;
    import java.awt.*;
    
    public class guiExampleProblem {
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    final MyWindows wnd = new MyWindows("guiExampleProblem");
                    wnd.setVisible(true);
                }
            });
        }
    }
    
    class MyWindows extends JFrame {
        public MyWindows(String text) {
            super(text);
    
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);        
    
            JPanel mainPanel = new JPanel();
            mainPanel.setLayout(new FlowLayout());      
    
    
            JPanel containerPanel1 = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(this.getParent().getWidth(),60);
                }
            };
            JPanel containerPanel2 = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(this.getParent().getWidth(),60);
                }
            };
            JPanel containerPanel3 = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(this.getParent().getWidth(),60);
                }
            };
            containerPanel1.setBackground(Color.BLACK);
            containerPanel2.setBackground(Color.RED);
            containerPanel3.setBackground(Color.GREEN); 
    
            mainPanel.add(containerPanel1);
            mainPanel.add(containerPanel2);
            mainPanel.add(containerPanel3);
    
    
            this.add(mainPanel);
            pack();
        }   
    }
    

    【讨论】:

    • 坏主意 - 尺寸提示预计会根据内容(和/或儿童)而不是父母返回尺寸。执行后者可能会产生意想不到的结果,甚至会挂起应用程序。由于 BoxLayout 尊重组件的 maxSize,因此要采用的方法是覆盖 getMaxSize 以返回一些高度限制。
    【解决方案2】:

    将要拉伸的面板(使用 BoxLayout)放在 BorderLayout 的 CENTER 中 - 将面板放在该 BorderLayout 的 EAST 的右侧。您没有详细说明您还希望它做什么,也没有提供任何代码,但这可能是您想要的。

    --

    在您的解决方案之后:在我看来,在这里使用 FlowLayout 会让人感到困惑——它水平地一个接一个地布置其组件,而您从容器宽度获取首选大小的技巧使其表现不同。我也尽可能避免在我的应用程序中使用布局逻辑,所以我寻找另一种方法来做到这一点并想出了:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.WindowConstants;
    
    public class guiExampleProblem2
    {
      public static void main(String[] args)
      {
        SwingUtilities.invokeLater(new Runnable()
        {
          @Override
          public void run()
          {
            final MyWindows2 wnd = new MyWindows2("guiExampleProblem2");
            wnd.setVisible(true);
          }
        });
      }
    }
    
    class MyWindows2 extends JFrame
    {
      public MyWindows2(String text)
      {
        super(text);
    
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
    
        JPanel containerPanel1 = addContainedPanel(Color.BLACK, 60, 60, mainPanel);
        JPanel containerPanel2 = addContainedPanel(Color.RED,   60, 60, mainPanel);
        JPanel containerPanel3 = addContainedPanel(Color.GREEN, 60, 60, mainPanel);
    
        this.add(mainPanel, BorderLayout.NORTH);
    
        pack();
      }
    
      JPanel addContainedPanel(Color color, int width, int height, JPanel container)
      {
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(width, height));
        panel.setBackground(color);
        container.add(panel);
        return panel;
      }
    }
    

    这使用 BorderLayout 的 NORTH 部分(顺便说一下,这是 JFrame 的默认布局)来完成您想要的主要事情——水平拉伸。带有页面轴的 BoxLayout 旨在从上到下进行布局,因此我认为这不会让读者感到困惑。无论如何,我认为这是使用组件(包括布局管理器)的另一种方式,更像是它们的预期和记录。

    【讨论】:

    • 感谢您的回复,我已将我的问题更新为更具体。
    猜你喜欢
    • 2017-08-08
    • 2022-12-01
    • 1970-01-01
    • 2023-03-08
    • 2017-12-03
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 2019-01-22
    相关资源
    最近更新 更多