我有一个JPanel父级,里面有3个JPanel子级。他们目前都使用GridLayout并一起代表一个UML类。问题是,当我添加新属性或方法时,所有3个JPanel都会增长到相同的大小。
欲望行为是:
无论何时添加方法/属性,父JPanel都可以自动增长/缩小。我正在玩GridBagLayout atm,但我无法接近欲望的结果。
是否有一种简单(或简单)的方式来解决这个问题?!
这里有几张照片可以显示我的情况。
新创建的UML类=> 这就是它目前的行为方式=>
但我想要这个=> 或此=> 或此=>
Edit2:为了清晰起见添加了新的图片。如果原版有误导性,我非常抱歉。
Edit3: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);
}
}
帮助班:
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,它就是巨大的!它比容器大......
答案 0 :(得分:6)
我建议你使用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) ;
答案 1 :(得分:4)
也许通过使用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();
}
}
答案 2 :(得分:3)
不幸的是,我不是100%确定我理解你的布局。如果你能附上图片会更好。
但是如果网格布局增长不是你想要的,你可以使用GridBagLayout,它可以做几乎所有事情,但有点复杂或使用边框和其他布局的组合。
可能有几种边框布局可以帮到你。在这个布局中心正在快速增长,而北部,南部,西部和东部正在增长较慢。尝试使用它们。
也检查BoxLayout。
如果您要创建许多复杂的对话框,请查看MigLayout。虽然存在一些学习曲线,但这种布局确实可以帮助您节省时间和天数。
由于您现在更新了问题,我可以肯定地说您可以使用North,South和Center定义BorderLayout。
中心将包含2行的网格布局。每行将再次包含Border layeout。上边框布局将包含南部的其他面板。较低的边框布局将包含北方的边框布局。
每个布局都将包含另一个边框布局,其中西边是标签,中间是文本字段。
答案 3 :(得分:1)
您可以使用GridBagLayout。我认为对我有用的是