java哪个布局管理器适合这个任务?

我有一个JPanel父母,里面有3个JPanel孩子。 他们目前都使用GridLayout并一起代表一个UML类。 问题是,当我添加新属性或方法时,所有3个JPanel都会增长到相同的大小。

欲望的行为是:

  1. 每当添加方法或属性时,标题框的大小始终保持不变。
  2. 添加方法时,只有方法面板增长,标题和属性面板的大小保持不变。
  3. 添加属性时,只有属性面板增长,其他面板大小保持不变。

只要添加了方法/属性,父JPanel就可以自动增长/缩小。 我正在玩GridBagLayout atm,但我无法接近欲望的结果。

有一种简单(或更简单)的方式来解决这个问题吗?!

这里有几张照片可以展示我的情况。

新创建的UML类=> 在此处输入图像描述 这是它目前的表现方式=> 在此处输入图像描述

但我想要这个=> 在此处输入图像描述 或者这个=> 在此处输入图像描述 或者这个=> 在此处输入图像描述

Edit2:为了清晰起见添加了新的图片。 如果原始版本具有误导性,我非常抱歉。

编辑3:YESS! 我已经整理好了! 感觉就像永远! 这是SSEEC:

儿童小组

import java.awt.Component; import java.awt.Container; import java.awt.GridLayout; import java.awt.event.MouseEvent; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.event.MouseInputAdapter; import javax.swing.event.MouseInputListener; public class APanel extends JPanel{ private JTextField tf; public APanel() { this.setLayout(new GridLayout(0,1)); this.addMouseListener(mouseInputListener); } MouseInputListener mouseInputListener = new MouseInputAdapter() { @Override public void mouseClicked(MouseEvent e) { System.out.println("Adding a new text field!"); tf = MyTF.create("Double click"); addNewTF(tf); Component source = (Component) e.getSource(); Container c = source.getParent(); while(true) { if(c instanceof PPanel) break; else c=c.getParent(); } PPanel p = (PPanel) c; p.expand(); } }; public void addNewTF(JTextField tf) { this.add(tf); this.setSize(this.getWidth(), this.getHeight()+tf.getHeight()); this.revalidate(); this.repaint(); } } 

家长小组:

  import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; public class PPanel extends JPanel{ //private APanel panel1; private JPanel panel1; private APanel panel2; private APanel panel3; public PPanel() { this.setLayout(new BoxLayout(this , BoxLayout.Y_AXIS)); this.setBackground(Color.black); panel1 = new JPanel(); panel1.setLayout(new GridLayout(0,1)); panel1.add(new JTextField("title")); panel2 = new APanel(); panel2.setBorder(BorderFactory.createLineBorder(Color.red)); panel3 = new APanel(); panel3.setBorder(BorderFactory.createLineBorder(Color.black)); this.add(panel1); this.add(Box.createRigidArea(new Dimension(0,1))); this.add(panel2); this.add(panel3); } public void expand() { this.setSize(this.getWidth(), this.getHeight()+33); this.revalidate(); this.repaint(); } public static void main(String[] args) { JFrame frame = new JFrame(); PPanel panel = new PPanel(); panel.setBounds(10, 10, 100, 150); JPanel c = new JPanel(null); c.add(panel); frame.add(c); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(new Dimension(350, 300)); frame.setTitle("Demo"); frame.setLocationRelativeTo(null); frame.setVisible(true); } } 

帮助class:

  import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.event.MouseEvent; import javax.swing.JTextField; import javax.swing.event.MouseInputAdapter; import javax.swing.event.MouseInputListener; public class MyTF { public static JTextField create(String name) { final JTextField tf = new JTextField(name); System.out.println(tf.getPreferredSize()); tf.setPreferredSize(new Dimension(100,33)); tf.addMouseListener(mouseInputListener); return tf; } static MouseInputListener mouseInputListener = new MouseInputAdapter() { @Override public void mouseClicked(MouseEvent e) { Component source = (Component) e.getSource(); Container c = source.getParent(); while(true) { if(c instanceof PPanel) break; else if(c instanceof APanel) { c.dispatchEvent(e); c = c.getParent(); break; } else c=c.getParent(); } c.dispatchEvent(e); } }; } 

我放弃了使用GridBagLayout玩的efford,这对我来说太过分了。 然后我按照建议尝试了borderLayout但是无法让它像我想要的那样工作。 然后最后BoxLayout,它应该工作但我的代码中有一个错误! 因此,当我尝试使用0verbose代码建议并使用它时,它失败了! 直到我完成SSEEC,最后编译并在我决定发布之前运行它(此时我几乎放弃了)然后我意识到它有效…可以在自己的空间中成长的面板,他们不要互相干扰。

我就像WTF!

回到我的代码并比较它SSEEC和有一个错误,扩展面板高度的代码是在错误的地方,所以他们有点像吃进彼此的空间。

更好! 我可以指定中间框与其上方和下方的框之间的距离为一个像素。 这意味着我仍然可以使用mKorbel的技巧来绘制背线来分隔那些盒子!

编辑4:有没有办法让我设置一个组件的大小? 如果您运行SSEEC,您会注意到一旦添加了JTextField,它就是巨大的! 它比容器大……

我建议你使用BoxLayout。 这是一个教程 。 使用胶水和刚性区域,您可以获得几乎所有所需的布局。 在你的情况下,代码应该是这样的:

 JPanel container = new JPanel(); container .setLayout(new BoxLayout(container , BoxLayout.Y_AXIS)); JPanel childTop = new JPanel(); JPanel childCenter = new JPanel(); JPanel childBottom = new JPanel(); childTop.setMaximumSize(...); childBottom.setMaximumSize(...); container.add(childTop); container.add(Box.createVerticalGlue()); container.add(childCenter); container.add(Box.createVerticalGlue()); container.add(childBottom); 

当您需要插入新的孩子时,请记住将其插入正确的位置:在其中一个胶水和childCenter之间。 例如:

 container.add(newChild, 2) ; 

也许这通过使用BorderLayout你可以做到这一点

(关于基本内容的示例revalidate(); + repaint();pack();

在此处输入图像描述在此处输入图像描述在此处输入图像描述

来自代码

 import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.LineBorder; public class AddComponentsAtRuntime { private JFrame f; private JPanel panel; private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack; public AddComponentsAtRuntime() { JButton b = new JButton(); b.setBackground(Color.red); b.setBorder(new LineBorder(Color.black, 2)); b.setPreferredSize(new Dimension(600, 10)); panel = new JPanel(new GridLayout(0, 1)); panel.add(b); JPanel panelnorth = new JPanel(); panelnorth.setPreferredSize(panel.getPreferredSize()); f = new JFrame(); f.setLayout(new BorderLayout(5, 5)); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(panelnorth,BorderLayout.NORTH); f.add(panel,BorderLayout.CENTER); f.add(getCheckBoxPanel(),BorderLayout.SOUTH); f.setLocation(200, 200); f.pack(); f.setVisible(true); } private JPanel getCheckBoxPanel() { checkValidate = new JCheckBox("validate"); checkValidate.setSelected(false); checkReValidate = new JCheckBox("revalidate"); checkReValidate.setSelected(false); checkRepaint = new JCheckBox("repaint"); checkRepaint.setSelected(false); checkPack = new JCheckBox("pack"); checkPack.setSelected(false); JButton addComp = new JButton("Add New One"); addComp.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JButton b = new JButton(); b.setBackground(Color.red); b.setBorder(new LineBorder(Color.black, 2)); b.setPreferredSize(new Dimension(600, 10)); panel.add(b); makeChange(); System.out.println(" Components Count after Adds :" + panel.getComponentCount()); } }); JButton removeComp = new JButton("Remove One"); removeComp.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int count = panel.getComponentCount(); if (count > 0) { panel.remove(0); } makeChange(); System.out.println(" Components Count after Removes :" + panel.getComponentCount()); } }); JPanel panel2 = new JPanel(); panel2.add(checkValidate); panel2.add(checkReValidate); panel2.add(checkRepaint); panel2.add(checkPack); panel2.add(addComp); panel2.add(removeComp); return panel2; } private void makeChange() { if (checkValidate.isSelected()) { panel.validate(); } if (checkReValidate.isSelected()) { panel.revalidate(); } if (checkRepaint.isSelected()) { panel.repaint(); } if (checkPack.isSelected()) { f.pack(); } } public static void main(String[] args) { AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime(); } } 

不幸的是,我不是100%确定我理解你的布局。 如果你能附上图片会更好。

但是如果网格布局增长不是你想要的,你可以使用GridBagLayout,它可以做几乎所有事情,但有点复杂或使用边框和其他布局的组合。

可能有几种边框布局可以帮到你。 在这个布局中心正在快速增长,而北部,南部,西部和东部正在增长较慢。 尝试使用它们。

检查BoxLayout。

如果您要创建许多复杂的对话框,请查看MigLayout 。 虽然存在一些学习曲线,但这种布局确实可以帮助您节省时间和天数。

既然你现在更新了你的问题,我肯定可以说你可以用North,South和Center定义BorderLayout。

中心将包含2行的网格布局。 每行将再次包含Border layeout。 上边框布局将包含南部的其他面板。 较低的边框布局将包含北方的边框布局。

每个布局都将包含另一个边框布局,其中西边是标签,中间是文本字段。

您可以使用GridBagLayout。 我认为对我有用的是

  • 将第四个子面板添加到顶部面板
  • 将前三个面板的权重设置为0
  • 将底部(新)面板的重量设置为1
  • 根据您用于在子面板中呈现文本的技术,您可能需要明确设置子面板的首选大小。
  • 当您向子面板添加新项目时,您需要使整个项目无效并重新布局。