2011-08-28 88 views
4

我有一个JPanel父亲,里面有3个JPanel儿童。他们目前都使用GridLayout并一起表示一个UML类。问题是,当我添加一个新的属性或方法时,所有3个JPanel增长到相同的大小。java哪个布局管理器适合这个任务?

欲望的行为是:

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

无论何时添加方法/属性,父JPanel都可以自动增长/缩小。我正在与GridBagLayout atm玩弄,但我无法接近渴望的结果。

有没有一个简单的(或更简单)的方法来解决这个问题?

这里有几张图片来显示我的情况。

新创建UML类=> enter image description here这是它目前的行为=>enter image description here

但我想这=>enter image description here或本=>enter image description here或本=>enter image description here

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

援助类:

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

    }; 
} 

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

我就像跆拳道!

回到我的代码,并将其与SSEEC进行比较,发现有一个错误,扩展面板高度的代码位于错误的位置,所以它们有点像进入彼此的空间。

更棒了!我可以指定中间框与上方和下方框之间的距离为一个像素。这意味着我仍然可以使用mKorbel的技巧来划分这些盒子的底线!

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

+0

投入一些草图可能很有用,但我在查看你想要的内容时遇到了一些麻烦。 – Jeffrey

+0

你走了。现在好点了吗? – bili

+0

如果JPanel在中心区域(在新的Atribute中添加并增加大小),则可以调整在北部和南部区域的JPanels的大小(减小SIZE) – mKorbel

回答

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

-1 setXXSize – kleopatra

+0

@kleopatra:你为什么反对setXXSize方法?你能解释我有什么问题吗? – Heisenbug

+0

我当然可以 - 只是:你做了什么来找到自己的?作为f.i. @bendicott在评论中做了我的答案http://stackoverflow.com/questions/7074514/images-in-jtable-cells-off-by-one-pixel – kleopatra

3

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

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

也许几个边界布局可以帮助你。在这个布局中心增长很快,而北部,南部,西部和东部增长较慢。尝试使用它们。

也选中BoxLayout。

如果您打算创建很多复杂的对话框,请查看MigLayout。尽管存在一些学习曲线,但这种布局确实可以帮助您节省数小时和数天。

既然你现在更新了你的问题,我可以肯定地说,你可以定义BorderLayout,北,南和中心。

中心将包含2行的网格布局。每行将包含边界layeout。上部边界布局将包含南部的其他面板。下边界布局将包含北部的边界布局。

每一个布局将包含另一个边界layouy在西部的标签和中心的文本字段。

+0

我已经添加了几张图片。看我的OP。我不是只创建一个盒子,并试图让它表现良好! – bili

1

可以使用GridBagLayout的这一点。我认为什么工作对我来说是

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

这也许通过使用BorderLayout的,你可以做(​​约基本的东西revalidate(); + repaint();pack();为例)从代码

enter image description here enter image description here enter image description here

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(); 
    } 
} 
+0

+ 1:总是有用和完整的例子;) – Heisenbug

+0

+1也出于同样的原因,由0verbose陈述!谢谢! – bili