简体   繁体   English

防止 MigLayout 为组件分配空间

[英]Prevent MigLayout from assigning space to a component

I have a JFrame that consists of a potentially arbitrarily-large set of "headers" which can be clicked on to expose panels, one per header (conceptually similar to a vertically-arranged toolbar, with the headers being tabs that expose various tool panels).我有一个 JFrame,它由一组可能任意大的“标题”组成,可以单击以显示面板,每个标题一个(概念上类似于垂直排列的工具栏,标题是显示各种工具面板的选项卡) . I want the headers to have a fixed amount of vertical space assigned to them, but to grow horizontally to fill the width of the frame.我希望标题有固定数量的垂直空间分配给它们,但水平增长以填充框架的宽度。 I want the panels exposed by the headers to consume all excess vertical space in the frame -- but only if they're visible;我希望标题暴露的面板消耗框架中所有多余的垂直空间——但前提是它们是可见的; when invisible they should take zero space.当不可见时,它们应该占用零空间。

Unfortunately, no matter how I try to tweak the layout, I can't keep it from assigning extra space to the headers and to invisible panels.不幸的是,无论我如何尝试调整布局,我都无法阻止它为标题和不可见面板分配额外的空间。 In the demo app, simply make the window larger.在演示应用程序中,只需将窗口放大即可。 The desired behavior is that the blue "Hello 0" panel should grow taller while all other components stay "compact";期望的行为是蓝色的“Hello 0”面板应该变高,而所有其他组件保持“紧凑”; in practice I see empty space around the two "Compact label" labels and below the two lower "Click me" headers.实际上,我在两个“Compact label”标签周围和两个较低的“Click me”标题下方看到了空白区域。

Thanks for your time!谢谢你的时间!

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);
   }
}

It might be best to use a JTabbedPane to get what you want. 最好使用JTabbedPane获得所需的内容。

Otherwise you can put percentage width and height constraints on your components. 否则,您可以在组件上放置宽度和高度百分比约束。 So for your headers you can tell them to use 100% of the width with: 因此,对于标题,您可以告诉他们使用以下宽度的100%:

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

For the body you can put "h 100%" (you can use h or height) 对于身体,您可以输入“ h 100%”(可以使用h或height)

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

It's not perfect, but hopefully this helps. 它并不完美,但希望能有所帮助。

Ultimately I had to resort to removing and re-adding components to the layout manager, using different constraints depending on whether or not a given body was visible. 最终,我不得不诉诸于删除和重新添加组件到布局管理器,根据给定主体是否可见使用不同的约束。 This isn't ideal, but it does result in the desired behavior. 这不是理想的,但确实会导致所需的行为。 MigLayout does have a setComponentConstraints() method which you'd think would work for this, but, like Matt Hubbard's suggestion, it doesn't recalculate sizes when the bodies are shown/hidden, resulting in an uneven distribution of space to the visible bodies. MigLayout确实有一个setComponentConstraints()方法,您认为可以使用该方法,但是,就像Matt Hubbard的建议一样,当显示/隐藏物体时,它不会重新计算尺寸,从而导致可见物体的空间分布不均匀。

Here's the updated demo program: 这是更新的演示程序:

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);
   }
}

I think what you're looking for is the hidemode command.我认为您正在寻找的是hidemode命令。 This will prevent MigLayout from assigning space to a component that is not yet visible.这将阻止 MigLayout 为尚不可见的组件分配空间。

I'll leave this SO question here which explains how to use this option.我将把这个SO 问题留在这里,它解释了如何使用这个选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM