我正在尝试将JPanel
("父面板")的内容从顶部添加到底部,并使每个组件的宽度与宽度相匹配父面板,同时具有每个组件的高度包装内容。内容将动态生成。
这就是我喜欢的样子:
这在Android中相当容易。我查看了Swing LayoutManagers,但它们似乎都不是一个明显的选择。我已经尝试使用Boxlayout
(垂直),除了没有填充父面板宽度的面板之外,它的工作原理(这使得它看起来非常糟糕)。
感谢任何建议!
修改
感谢camickr的回答,我明白了。如果它将来会帮助任何人,我提供了我的代码和截图。
解决问题的代码:
(注意使用GridBagLayout,BorderLayout和GridBagConstraints的参数)
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;
}
}
正在运行的应用程序的屏幕截图:
答案 0 :(得分:1)
不太了解你的问题。您通常不会随机包装文本,按钮和组合框。通常,面板具有布局,因此组件在逻辑上是有组织的。那就是你不想要一个带有&#34; First Name&#34;等文字的标签。然后是一个随机包装到下一行的文本字段。
在我看来,你有一个&#34;详细的面板&#34;你隐藏或显示?
您可以使用BorderLayout实现此功能。因此隐藏/显示按钮将放置在BorderLayout.PAGE_START中。然后详细信息面板将位于BorderLayout.CENTER中。然后根据需要设置详细信息面板的可见性。
然后顶级容器可以是GridBagLayout
。您可以使用约束使每行填充单元格的宽度。每个子面板都可以使用Border
在左侧稍微缩进。
阅读Swing tutorial。有以下部分: