【问题标题】:Prevent MigLayout from assigning space to a component防止 MigLayout 为组件分配空间
【发布时间】:2016-05-28 03:36:53
【问题描述】:

我有一个 JFrame,它由一组可能任意大的“标题”组成,可以单击这些“标题”以显示面板,每个标题一个(概念上类似于垂直排列的工具栏,标题是显示各种选项卡的选项卡)工具面板)。我希望标题有固定数量的垂直空间分配给它们,但水平增长以填充框架的宽度。我希望标题暴露的面板消耗框架中所有多余的垂直空间——但前提是它们是可见的;当不可见时,它们应该占用零空间。

不幸的是,无论我如何尝试调整布局,我都无法阻止它为标题和不可见的面板分配额外的空间。在演示应用程序中,只需将窗口放大即可。期望的行为是蓝色的“Hello 0”面板应该变得更高,而所有其他组件保持“紧凑”;在实践中,我看到两个“紧凑标签”标签周围和两个较低的“点击我”标题下方有空白区域。

感谢您的宝贵时间!

public class Demo {
   public static void main(String[] args) {
      final JFrame frame = new JFrame("Inspector");
      frame.setLayout(new MigLayout("debug, fill, flowy, insets 0, gap 0"));
      frame.add(new JLabel("Compact label 1"));
      frame.add(new JLabel("Compact label 2"));
      for (int i = 0; i < 3; ++i) {
         JPanel wrapper = new JPanel(
               new MigLayout("debug, fill, flowy, insets 0, gap 0",
                  "", "0[]0[grow]0"));
         // Fixed-height header should grow horizontally only
         JPanel header = new JPanel(
               new MigLayout("flowx, fillx, insets 0, gap 0"));
         header.add(new JLabel("Click me!"), "growx, height 40!");
         header.setBackground(Color.RED);
         // Variably-sized body should fill any extra space.
         final JPanel body = new JPanel(new MigLayout("fill"));
         body.add(new JLabel("Hello, " + i), "grow");
         body.setBackground(Color.BLUE);
         body.setVisible(i == 0);
         wrapper.add(header, "growx");
         wrapper.add(body, "growy, hidemode 2");
         header.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
               boolean shouldShow = !body.isVisible();
               body.setVisible(shouldShow);
               frame.pack();
            }
         });
         frame.add(wrapper, "grow");
      }
      frame.pack();
      frame.setVisible(true);
   }
}

【问题讨论】:

    标签: java swing miglayout


    【解决方案1】:

    最好使用JTabbedPane 来获得你想要的东西。

    否则,您可以对组件设置百分比宽度和高度限制。 因此,对于您的标题,您可以告诉他们使用 100% 的宽度:

    wrapper.add(header, "growx , w 100%");
    

    对于身体,你可以输入“h 100%”(你可以使用 h 或 height)

    wrapper.add(body, "growy, hidemode 2, h 100%");
    

    它并不完美,但希望这会有所帮助。

    【讨论】:

    • JTabbedPane 在这里没有做我想要的,即拥有多个不同的面板,可以通过单击它们的标题栏来独立显示/隐藏。我对标题也有特殊的渲染要求,我的示例中没有包含这些要求。您的高度技巧的工作原理是没有为不可见的正文或标题分配额外的空间,具有奇怪的副作用,即当单击标题时,相应的正文会以其最小尺寸出现 - 最好是所有正文在它们之间分配相同的高度。
    • 另外,如果您有两个可见的主体,并且反复单击一个标题,则另一个标题将重复增长。我尝试手动设置每个主体(或相应包装器)的大小,但布局管理忽略了我的大小设置,大概是因为它们不是布局约束的形式。
    • 看看JOutlookBar。我相信你可以编辑它以更接近你想要的。
    【解决方案2】:

    最终我不得不求助于删除和重新添加组件到布局管理器,根据给定的主体是否可见使用不同的约束。这并不理想,但确实会产生所需的行为。 MigLayout 确实有一个 setComponentConstraints() 方法,你认为它可以解决这个问题,但是,就像马特哈伯德的建议一样,它不会在显示/隐藏实体时重新计算大小,导致空间分布不均匀可见的身体。

    这是更新后的演示程序:

    public class Demo {
       public static void main(String[] args) {
          final JFrame frame = new JFrame("Inspector");
          final JPanel contents = new JPanel(
                new MigLayout("debug, fill, flowy, insets 0, gap 0"));
          contents.setBackground(Color.GRAY);
          frame.add(contents);
          final ArrayList<Component> components = new ArrayList<Component>();
          components.add(new JLabel("I should not grow"));
          components.add(new JLabel("I shouldn't grow either"));
          for (int i = 0; i < 3; ++i) {
             // Fixed-height header should grow horizontally only
             final JPanel header = new JPanel(
                   new MigLayout("flowx, fillx, insets 0, gap 0"));
             header.add(new JLabel("Click me!"), "growx, height 40!");
             header.setBackground(Color.RED);
             components.add(header);
             // Variably-sized body should fill any extra space.
             final JPanel body = new JPanel(new MigLayout("fill"));
             body.add(new JLabel("Hello, " + i), "grow");
             body.setBackground(Color.BLUE);
             body.setVisible(i == 0);
             components.add(body);
             header.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                   boolean shouldShow = !body.isVisible();
                   body.setVisible(shouldShow);
                   refill(frame, contents, components);
                }
             });
          }
          refill(frame, contents, components);
          frame.setVisible(true); 
       } 
       private static void refill(JFrame frame, JPanel contents,
             ArrayList<Component> components) {
          contents.removeAll();
          for (int i = 0; i < components.size(); ++i) {
             Component component = components.get(i);
             // First two components don't grow at all.
             if (i < 2) {
                contents.add(component, "gap 0, grow 0, pushy 0");
             }
             // Even-numbered components are headers.
             else if (i % 2 == 0) {
                contents.add(component, "gap 0, growx, growy 0, pushy 0");
             }
             // Odd-numbered components are bodies, only if visible.
             else if (component.isVisible()) {
                contents.add(component, "gap 0, grow, pushy 100");
             }
          }
          Dimension curSize = frame.getSize();
          frame.pack();
          frame.setSize(curSize);
       }
    }
    

    【讨论】:

      【解决方案3】:

      我认为您正在寻找的是hidemode 命令。这将防止 MigLayout 为尚不可见的组件分配空间。

      我将把这个SO question 留在这里,它解释了如何使用这个选项。

      【讨论】:

        猜你喜欢
        • 2018-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-02
        • 2020-07-28
        • 1970-01-01
        相关资源
        最近更新 更多