我有一个带有3个JPanel子级的JPanel父级。它们当前都使用GridLayout并共同表示一个UML类。问题是,当我添加新的属性或方法时,所有3个JPanel都会增长到相同的大小。
期望行为是:

  • 每当添加方法或属性时,标题框的大小始终保持不变。
  • 添加方法时,仅方法面板会增长,并且标题和属性面板的大小保持不变。
  • 添加属性后,只有属性面板会增加,其他面板大小保持不变。

  • 每当添加方法/属性时,父级JPanel已经可以自动增长/缩小。我正在玩GridBagLayout atm,但是我远未达到期望的结果。
    我有一种简单(或更简单)的方法来解决这个问题吗?
    这里有几张照片可以显示我的情况。
    新创建的UML类=>
    这是当前的行为=>
    但是我想要这个=>或这个=>或这个=>
    Edit2:为清晰起见添加了新图片。非常抱歉,如果原始版本有误导性。
    Edit3:是的!我已经排序了!感觉就像永远!这是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);
        }
    }
    
    帮助班:
        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。这是tutorial。使用胶水和刚性区域,您可以获得几乎所有所需的布局。在您的情况下,代码应如下所示:

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

    07-24 18:50