【问题标题】:Adding panel with without layout to the NORTH of BorderLayout将无布局的面板添加到 BorderLayout 的 NORTH
【发布时间】:2013-06-15 02:49:28
【问题描述】:

同事。

我正在尝试用 Java 构建简单的 GUI,其中 JFrame 具有边框布局。我想把带有 JTable 的 JScrollPane 放到 CENTER,把没有布局的 JPanel 放到 NORTH。

问题是 JPanel 不可见。有一个简单的问题示例:

JFrame frame = new JFrame("Test frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JButton button = new JButton("Test button");
button.setBounds(10, 10, 40, 20);

JPanel panelN = new JPanel(null); // layout = null, panelN without layout
panelN.add(button);
frame.add(panelN, BorderLayout.NORTH);

JTable table = new JTable(new DefaultTableModel(4, 4));
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane, BorderLayout.CENTER);

frame.setSize(400, 400);
frame.setVisible(true);

【问题讨论】:

  • 在面板中使用 layoutManager
  • @dumas45,没有充分的理由使用空布局。按照设计使用的方式使用 Swing,并使用布局管理器。
  • 问题是,在布局管理器中,父容器不知道子面板的大小,所以它的大小为 0x0,这是一个组件的默认大小
  • 我发现 setPreferredSize 方法有帮助并且面板变得可见。如果我在创建 GUI 之前使用JFrame.setDefaultLookAndFeelDecorated(true);,我希望 GUI 在 Linux、Windows 和其他操作系统上也一样。不是吗?

标签: java swing layout border-layout absolutelayout


【解决方案1】:

您必须使用LayoutManager。完全不鼓励不使用 layoutManager,但如果你想要这个,你也必须将panel.setBounds(..) 设置为面板。

默认情况下JPanelFlowLayout 所以如果你放

JPanel panelN = new JPanel(); // FlowLayout used 
panelN.add(button);
frame.add(panelN, BorderLayout.NORTH);

所以你的框架看起来像这样。

布局管理器确定容器内组件的大小和位置。虽然组件可以提供大小和对齐提示,但容器的布局管理器对容器内组件的大小和位置拥有最终决定权。

强烈建议您例如,如果您必须调整组件大小或以不同的分辨率显示,则将此工作委托给布局管理器

【讨论】:

    【解决方案2】:

    我不知道 null 布局的预期行为,但如果没有进一步的要求,您不妨使用零参数构造函数进行实例化:

    new JPanel();
    

    【讨论】:

    【解决方案3】:

    如果您没有为面板设置任何布局,则在添加组件时,面板不知道将组件放在哪里,所以基本上组件不会显示,直到您设置特定的通过component.setBounds(x,y,width,hieght)方法一一定位组件。

    请注意,由于平台不同,删除布局管理器不是一个好习惯,假设您的程序在 Window 和 MacOS 和 Linux 上运行,您最好使用布局管理器。

    还可以查看this post 并查看@Andrew Thompson 对我的回答的评论:

    Java GUI 可能必须在不同的平台上工作 屏幕分辨率和使用不同的 PLAF。因此他们不是 有利于元件的准确放置。对于健壮的 GUI,改为 使用布局管理器或它们的组合以及布局 空白的填充和边框,用于组织组件。

    毕竟: 如果您有要求或任务告诉您必须使用绝对布局,请使用它,否则请避免使用它。

    【讨论】:

    • 我不知道为什么这会得到两个赞成票。这仍然无助于OP。问题在于将面板添加到 NORTH。此解决方案无济于事。这是不应使用空布局的另一个原因。需要完成太多的手动编码,人们不知道所有的小问题。底线是正确的答案应该是使用布局管理器。
    • @camickr:我提到了解决方案,但你不认为告诉他要求的消极方面会有帮助吗?
    • 问题是 p,默认情况下,首选大小为 0x0,这只是运气问题,您添加 p 的容器正在使用不使用其首选大小的布局管理器子组件来确定布局结果 - 仍然是 OP 面临的相同问题 - 没有解决任何问题
    • @MadProgrammer:我的错误,这个例子是用于框架内的按钮而不是面板,谢谢我编辑它。
    • 其实现在我觉得更糟了
    【解决方案4】:

    可以使用没有布局管理器的容器,因为您实际上可以将容器的布局设置为 NULL。使用 setBounds() 定位组件是一个好主意。但在这种情况下,您只需要考虑您的容器。它需要多大?布局管理器会为您计算,如果您没有,则必须根据您添加到其中的组件自行设置面板的大小。

    正如其他人在这里指出的那样,框架的边框布局管理器需要 NORTH 面板的首选大小(实际上是首选高度)。你必须设置它,否则值将为零,容器将变得不可见。请注意,对于 CENTER 面板,这不是必需的,因为它可以获得所有可能的空间。

    我之前遇到过像你这样的问题,我写了一个快速函数来根据给定组件的边界调整容器的大小。它将与显示该组件所需的一样大,因此考虑了尺寸 (w,h) 和位置 (x,y)。添加所有组件后,有一个“自动调整大小”版本可以使用一次。

    public static void updatePreferredSize(Container cont, Component comp) {
    
        int w = cont.getPreferredSize().width;
        int h = cont.getPreferredSize().height;
    
        int W = comp.getBounds().x + comp.getBounds().width;
        int H = comp.getBounds().y + comp.getBounds().height;
    
        if (W>w||H>h) cont.setPreferredSize(new Dimension(W>w?W:w, H>h?H:h));
    }
    
    public static void autoPreferredSize(Container cont) {
    
        for (Component comp : cont.getComponents())
            updatePreferredSize(cont, comp);
    }
    

    您可以在将每个组件添加到面板后使用 updatePreferredSize(),或者在所有添加后使用一次 autoPreferredSize()。

    // [...]
    panelN.add(button);
    updatePreferredSize(panelN, button);
    // [...]
    
    // or...
    
    // [...]
    autoPreferredSize(panelN);
    // [...]
    frame.setVisible(true);
    

    这样,如果您没有将北面板高度设置为固定值,则借助这些函数,您可以期望您的按钮将根据您使用 setBounds() 设置的位置可见。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      • 2014-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多