Java JPanel具有与父级宽度匹配的子级,并包装内容的高度

Java JPanel具有与父级宽度匹配的子级,并包装内容的高度,java,swing,layout-manager,Java,Swing,Layout Manager,我试图使JPanel(“父面板”)的内容从顶部向底部添加,并使每个组件的宽度与父面板的宽度匹配,同时使每个组件的高度包裹内容。内容将动态生成 这就是我想要的样子: 这在Android中是相当容易做到的。我调查过Swing的裁员经理,但他们似乎都不是一个明显的选择。我尝试过使用Boxlayout(垂直),除了没有填充父面板宽度的面板(这使它看起来非常糟糕)外,它也可以工作 谢谢你的建议 编辑: 多亏了卡米克尔的回答,我才明白。为了将来对任何人都有帮助,我提供了我的代码和屏幕截图 解决问题的代码:

我试图使
JPanel
(“父面板”)的内容从顶部向底部添加,并使每个组件的宽度与父面板的宽度匹配,同时使每个组件的高度包裹内容。内容将动态生成

这就是我想要的样子:

这在Android中是相当容易做到的。我调查过Swing的裁员经理,但他们似乎都不是一个明显的选择。我尝试过使用
Boxlayout
(垂直),除了没有填充父面板宽度的面板(这使它看起来非常糟糕)外,它也可以工作

谢谢你的建议

编辑:

多亏了卡米克尔的回答,我才明白。为了将来对任何人都有帮助,我提供了我的代码和屏幕截图

解决问题的代码:

(注意GridBagLayout、BorderLayout和GridBagConstraints参数的使用)

导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.GridBagConstraints;
导入java.awt.GridBagLayout;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
导入java.util.Random;
导入javax.swing.BorderFactory;
导入javax.swing.BoxLayout;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
公共类测试扩展了JFrame{
私有最终颜色暗绿色=Color.decode(“#388E3C”);
私有最终颜色绿色=Color.decode(#4CAF50”);
私有最终颜色浅绿色=Color.decode(#C8E6C9”);
公共静态void main(字符串[]args){
测试=新测试();
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
int nooftiles=4;
int noOfSubTitles=3;
随机=新随机();
公开考试(){
JPanel parentPanel=新的JPanel();
此.设置尺寸(新尺寸(300800));
此.setContentPane(父面板);
parentPanel.setBackground(颜色:白色);
//将父面板的布局设置为Gridlayout
setLayout(新的GridBagLayout());
//我们的头衔小组
JPanel titlesPanel=新的JPanel();
titlesPanel.setLayout(新的BoxLayout(titlesPanel,BoxLayout.Y_轴));

对于(int i=0;i而言,我并不真正理解您的问题。您通常不会随机包装文本、按钮和组合框。通常,面板具有布局,因此组件在逻辑上是有组织的。也就是说,您不希望标签上的文本(如“名字”)后跟随机包装到下一行的文本字段

在我看来,你有一个隐藏或显示的“细节面板”

您可以使用BorderLayout实现这一点。因此,隐藏/显示按钮将放置在BorderLayout.PAGE_START中。然后,详细信息面板将位于BorderLayout.CENTER中。然后,您可以根据需要设置详细信息面板的可见性

然后顶级容器可以是
GridBagLayout
。您可以使用约束让每一行填充单元格的宽度。每个子面板可以使用
边框
使其在左侧略微缩进

请阅读。有以下部分:

  • 如何使用GridBagLayout和
  • 如何使用边框

  • 另请参见
    org.netbeans.swing.outline.outline
    ,参见和。
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.util.Random;
    
    import javax.swing.BorderFactory;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    
    public class Test extends JFrame{
    
        private final Color darkGreen = Color.decode("#388E3C");
        private final Color green = Color.decode("#4CAF50");
        private final Color lightGreen = Color.decode("#C8E6C9");
    
        public static void main(String[] args){
            Test test = new Test();
            test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    
        int noOfTitles = 4;
        int noOfSubTitles = 3;
        Random random = new Random();
    
        public Test(){
    
    
            JPanel parentPanel = new JPanel();
            this.setSize(new Dimension(300,800));
            this.setContentPane(parentPanel);
            parentPanel.setBackground(Color.white);
    
            //Set layout of parent panel to Gridlayout
            parentPanel.setLayout(new GridBagLayout());
    
            //Panel for our titles
            JPanel titlesPanel = new JPanel();
            titlesPanel.setLayout(new BoxLayout(titlesPanel, BoxLayout.Y_AXIS));
    
            for(int i = 0;i<noOfTitles;i++){
                //Panel for the subtitles of each title
                JPanel subTitlesPanel = new JPanel();
                subTitlesPanel.setLayout(new BoxLayout(subTitlesPanel, BoxLayout.Y_AXIS));
    
                for(int j = 0;j<noOfSubTitles;j++){
                    //Get a panel with a title header, a collapse/uncollapse button and some sample content
                    subTitlesPanel.add(getCollapsiblePanel(getSampleContent(),"Subtitle"));
                    subTitlesPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
                }
                //Get a panel with a title header, a collapse/uncollapse button and the subtitles as content
                titlesPanel.add(getCollapsiblePanel(subTitlesPanel,"Title"));
            }
    
            //The constraints for the 
            GridBagConstraints constraints = new GridBagConstraints();
            constraints.anchor = GridBagConstraints.PAGE_START;
            constraints.fill = GridBagConstraints.HORIZONTAL; //Fill the panels horizontally. A weightx is needed for this to work. 
            constraints.gridx = 1;
            constraints.gridy = 0;
            constraints.weightx = 1;    //Actually makes it fill
            parentPanel.add(titlesPanel,constraints);
    
            //To actually bump the rest of the other stuff to the top, 
            //we need something below with a weighty > 0
            constraints.gridy = 1;
            constraints.weighty = 1;
            constraints.anchor = GridBagConstraints.PAGE_END;
            parentPanel.add(new JLabel(""),constraints);
    
            this.setVisible(true);
        }
    
        /*
         * Gets a title for the supplied content-panel. 
         * The title includes the titleText and a button for collapsing/uncollapsing the content. 
         */
        private JPanel getCollapsiblePanel(JPanel content,String titleText){
            JPanel titlePanel = new JPanel();   //Top container for the title
            JPanel title = new JPanel();        //collapse/uncollapse button and title text
    
            title.setLayout(new BoxLayout(title,BoxLayout.X_AXIS));
            title.add(getToggleVisibilityIcon(content));
            title.add(new JLabel(" "+titleText));
    
            //A border layout is needed here for the fill of the parent panel to work 
            // (I tried with the box layout but it didn't work)
            titlePanel.setLayout(new BorderLayout());
            titlePanel.add(title,BorderLayout.PAGE_START);
            titlePanel.add(content,BorderLayout.CENTER);
    
            //Vanity
            title.setBackground(green);
            title.setBorder(BorderFactory.createEmptyBorder(1,1,2,1));
    
            return titlePanel;
        }
    
        /*
         * Not important, just generates a panel with some "sample" strings. 
         */
        private JPanel getSampleContent(){
            JPanel content = new JPanel();
            content.setLayout(new BoxLayout(content,BoxLayout.Y_AXIS));
            for(int i = 0; i<1+random.nextInt(3); i++){
                String sampleContent = "";
                for(int j = 0;j<1 + random.nextInt(5);j++){
                    sampleContent += "sample ";
                }
                JLabel sample = new JLabel(sampleContent);
                sample.setForeground(Color.decode("#111111"));
                content.add(sample);
            }
            content.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
            content.setBackground(lightGreen);
            return content;
        }
    
        /*
         * Method that returns a JLabel that will toggle the visibility of the 
         * supplied content panel upon clicking. 
         */
        private JLabel getToggleVisibilityIcon(JPanel content){
            JLabel icon = new JLabel(" V ");
            icon.setBackground(green);
            icon.setBorder(BorderFactory.createLineBorder(darkGreen,2));
            icon.setOpaque(true);
            icon.addMouseListener(new MouseListener(){
                private JPanel content;
                private JLabel icon;
                MouseListener init(JPanel content,JLabel icon){
                    this.content = content;
                    this.icon = icon;
                    return this;
                }
                @Override
                public void mouseClicked(MouseEvent e) {
                    if(content.isVisible()){
                        content.setVisible(false);
                        icon.setText(" > ");
                    }else{
                        content.setVisible(true);
                        icon.setText(" V ");
                    }
                }
    
                @Override
                public void mousePressed(MouseEvent e) {}
                @Override
                public void mouseReleased(MouseEvent e) {}
                @Override
                public void mouseEntered(MouseEvent e) {}
                @Override
                public void mouseExited(MouseEvent e) {}
            }.init(content,icon));
            return icon;
        }
    }