【问题标题】:Dynamically growing JPanel with BoxLayout (on a null layout)使用 BoxLayout 动态增长的 JPanel(在空布局上)
【发布时间】:2012-12-26 17:38:30
【问题描述】:

我在具有空布局的 JPanel 顶部有一个带有垂直 BoxLayout 的 JPanel。

我希望带有 BoxLayout 的 JPanel 随着组件的添加而增长。

查看此代码:

public static void main (String[] args) {
    JFrame f = new JFrame();
    f.setSize(500,500);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel total = new JPanel();
    total.setLayout(null);
    total.setSize(f.getWidth(),f.getHeight());
    total.setBackground(Color.green);
    JPanel box = new JPanel();
    box.setLocation(100,200);
    box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
    box.add(new JButton("test"));
    box.add(new JLabel("hey"));
    total.add(box);
    f.add(total);
    f.setVisible(true);
}

您会注意到没有显示任何组件。

如何使 JPanel “盒子”随着我添加更多组件(垂直添加)而动态增加。

提前:我需要“框”的位置正好在 100,200,所以请不要建议我不要使用空布局。我必须使用空布局。 “total”的空布局不应该影响我的问题的答案,它侧重于“box”面板。

【问题讨论】:

  • 添加组件时会发生什么?我认为在某些事件中您需要添加组件和 repaint()。
  • 您发布的代码不可运行。没有主要方法。
  • 那是main方法的代码……把它扔到main方法里就行了。 (好像我需要告诉你……)
  • 因为您选择丢弃 (恕我直言) Swing 必须提供的最强大的 API 资产之一,您未能履行它负责的工作......设置子组件的大小。
  • 一个简单的 LayoutManager 接管 sizing 同时让您控制 locatingRob's DragLayout

标签: java swing jpanel absolutelayout boxlayout


【解决方案1】:

通过丢弃布局管理器,您突然对它的工作负责。我可能会添加的工作,这并不容易......

基本上,给定您的示例,您未能设置子组件的大小...

JFrame f = new JFrame();
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel total = new JPanel();
total.setLayout(null);
total.setSize(f.getWidth(), f.getHeight());
total.setBackground(Color.green);

JPanel box = new JPanel();
box.setLocation(100, 200);
box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
box.add(new JButton("test"));
box.add(new JLabel("hey"));
box.setSize(100, 100);  // <-- Don't forget this..

total.add(box);
f.add(total);
f.setVisible(true);

就个人而言,我认为你是在自找麻烦,但我会知道什么......

一个更好的主意可能是使用类似EmptyBorder 的东西来提供填充...

JFrame f = new JFrame();
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel total = new JPanel(new BorderLayout());
total.setSize(f.getWidth(), f.getHeight());
total.setBackground(Color.green);
total.setBorder(new EmptyBorder(100, 200, 100, 200));

JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
box.add(new JButton("test"));
box.add(new JLabel("hey"));

total.add(box);
f.add(total);
f.setVisible(true);

更新了布局管理器示例

现在,如果所有布局管理器都无法满足您的要求,您可以尝试编写自己的布局管理器。这具有您需要从 null 布局管理器获得的好处以及集成到 Swing 的组件更改过程中的好处,而无需求助于 ComponentListenersContainerListeners

JPanel total = new JPanel();
total.setLayout(new SuperAwesomeBetterThenYoursLayout());

自定义布局管理器

public static class SuperAwesomeBetterThenYoursLayout implements LayoutManager {

    @Override
    public void addLayoutComponent(String name, Component comp) {
    }

    @Override
    public void removeLayoutComponent(Component comp) {
    }

    @Override
    public Dimension preferredLayoutSize(Container parent) {
        return new Dimension(100, 300);
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
        return new Dimension(100, 300);
    }

    @Override
    public void layoutContainer(Container parent) {
        boolean laidOut = false;
        for (Component child : parent.getComponents()) {
            if (child.isVisible() && !laidOut) {
                child.setLocation(200, 100);
                child.setSize(child.getPreferredSize());
            } else {
                child.setSize(0, 0);
            }
        }
    }
    
}

这基本上代表了无论如何你将不得不做的工作,但它的方式与 Swing 的设计方式相得益彰......

【讨论】:

  • +1 MadProgrammer 的好例子!创建自定义布局管理器要高级一些,但您以非常简单的方式完成了它,干得好。
【解决方案2】:

建议:

  • 几乎永远不要使用空布局。
  • 为什么不给总数JPanel一个BorderLayout
  • 然后使用JPanelBoxLayout 添加到BorderLayout.NORTH(或也称为BorderLayout.PAGE_START)位置。

编辑
你说,

提前:我需要“框”的位置正好在 100,200,所以请不要建议我不要使用空布局。我必须使用空布局。 “total”的空布局不应该影响我的问题的答案,它侧重于“box”面板。

我认为您再次对您的程序施加了不必要的限制。您可以通过在其周围放置一个该大小的空边框或通过其他方式轻松地将您的“框”放置在 100、200 处。但答案不是放弃使用 null 布局。

【讨论】:

  • 我需要“盒子”面板正好在那个位置,所以我必须使用空布局。但是......空布局不应该影响我的问题的答案。
  • @CodeGuy:但是您可以通过使用边框和其他方式将“框”放置在某个位置,是的,空布局直接影响您解决问题的能力。跨度>
  • 独立于空布局问题考虑问题。想一想这个问题:“如何制作具有垂直框布局的动态 JPanel,当您添加更多组件时会增加尺寸”
  • @CodeGuy 当您向容器添加组件时,容器无效,导致调用布局管理器,请求它应该布局其内容。其中一部分将确定容器的首选、最小和最大布局要求。通过删除更高容器的布局管理器,您破坏了这个过程,这意味着,当容器“尝试”增长时,您不会让它。这就是问题所在……
  • @CodeGuy 想一想这个问题:“如何制作具有垂直框布局的动态 JPanel,当您添加更多组件时会增加尺寸”完全正确 LayoutManager 负责做什么。如果你想把时间浪费在重新发明轮子上,耸耸肩,靠自己:其他人可能不会那么热情地浪费时间和精力......还有更多有趣的问题需要解决;-)
【解决方案3】:

马上,我会改变什么:

public static void main (String[] args) {
    JFrame f = new JFrame();
    //f.setSize(500,500);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel total = new JPanel();
    //total.setLayout(null); //<-- this is usually a bad idea, but you can keep it
    //                                if you want to specify an EXACT location
    //                                for your JPanel
    total.setPreferredSize(500, 500);
    total.setBackground(Color.green);
    JPanel box = new JPanel();
    //box.setLocation(100,200);
    box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
    box.add(new JButton("test"));
    box.add(new JLabel("hey"));
    total.add(box);
    f.add(total);
    f.pack();
    f.setVisible(true);
}

一旦你有了这个基础,你需要做的就是动态改变 JPanel 的大小:

panel.setSize(width, heightOfComponentWithin * numberOfComponents);
container.repaint(); //<-- Im not sure if you also have to call panel.repaint(),
//                           you probably don't have to.

我还建议使用滚动视图,以防 JPanel 开始消失。祝你好运!

【讨论】:

  • (您需要阅读 HoverCrafts 的答案和 cmets 才能意识到,虽然您的建议非常好 - OP 通常不会喜欢它 - 抱歉 - 我 +1 ;))
  • 不做任何手动调整大小/定位(OP 坚持,不是你的错 :-) don't use setXXSize ;-)
【解决方案4】:

可能是因为你还没有为 box JPanel 设置大小。

【讨论】:

  • 你是对的,但我个人会不遗余力地提出除此之外的任何建议 - 恕我直言...
  • 强调@MadProgrammer 的评论:如果您需要对顶级容器以外的任何其他东西进行手动定位/调整大小......您做错了。
猜你喜欢
  • 2014-06-09
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
相关资源
最近更新 更多