2012-01-05 22 views
3

在通过addremove手动交换组件后,我在容器上调用validate()。根据该文件,是用来引起容器容器在调用验证后不会自动调整大小

validate方法再次布置其 子组件。当容器的 子容器已被 显示后,应修改此容器的 子组件(添加到容器或从容器中移除,或者 已更改布局相关信息)。

短语“布局其子又”让我觉得,容器将相应调整自身的大小,但它没有。相反,在调用validate()后,我还需要调用pack()以查看其所有子组件。

这是为什么?难道我做错了什么?

+0

使用Swing时,我使用'revalidate()'。同样,它不会调整框架大小,但会调整Container的大小,这可能会导致布局发生变化。例如,如果容器位于滚动窗格中,则可能会看到添加或删除滚动条。 – camickr 2012-01-05 16:20:05

+0

@camickr - 可能会误解你的意思,但在容器上重新验证将永远不会调整容器的大小,只有它的子项 – kleopatra 2012-01-06 10:34:36

+0

@kleopatra,再次看我的评论,我想我应该没有使用术语“容器”。我使用的术语“容器”是指“jpanel”,并试图强调它只会影响“容器”内组件的布局。它不会调整顶层容器(JFrame,JDialog,JWindow)。 – camickr 2012-01-06 16:13:16

回答

5

(可能是由于这种模棱两可的描述latest javaDoc改变)

JavaDoc 7说,

验证方法用于使容器布置其子组件NTS 再次 ..

所以其只铺设的组件,而你又需要一个pack()

注意pack()明确表示,

此窗口的大小,以适合其子组件的首选大小和布局。

7

我认为你自己回答了你的问题,希望帮你这个演示

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); 
     f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(panel, "Center"); 
     f.add(getCheckBoxPanel(), "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:@mKorbel总是有很好的演示:) – COD3BOY 2012-01-05 14:37:56

+0

好的演示,可能会保持它的方便! – davidfrancis 2012-01-05 15:04:39

2

的根本,而微妙的假设,在这里打球:布局和大小有直接的关系,1对1情况并非如此,并且是Swing编程中的一个常见假设。尺寸是布局和尺寸约束的结果。

布局是:

  • 在您指定
  • 并给予我必须适应该空间内
  • 位置相对于这些组件的组件给出指定策略彼此空间的限制(BoxLayout,BorderLayout等等)

如果布局管理能适应你给它的成分,在不改变容器的整体尺寸,它不会改变容器的大小。另一方面,拨打pack是明确要求尽量减少正在使用的空间。这是你看到结果的根本原因。

有些事情你可以尝试:

  • 确保你设置你的组件/容器的最大尺寸,这将迫使部件尺寸限制重新进行布局
  • 时,请务必打电话pack()作为一种习惯
  • 尝试一些建议有关common layout issues

这是棘手与Swing,因为你要明白在p包括管道,布局管理器以及窗口系统的一些细节。当谈到Swing文档(以及所有的方法和做任何事情的几种不同方式)时,我尝试用“不采取任何措施”的方式阅读文档,这意味着“这种方法的最小可能性是什么文件意味着它可能会这样做“,除非你观察到其他行为,否则不要被认为它不止于此。

最后,我想补充一点,在一般的布局管理的作业没有大小容器的这么多,因为它是把部件在一些关系到彼此,根据布局战略(这在additional detail here讨论) 。这个想法是,通过适当的LayoutManager,您可以指定一个基本布局策略,结果当您调整窗口大小时,LayoutManager将智能地移动组件,以便您的UI继续遵循整体策略。通过这种方式,布局基本上是独立于其工作空间的整体大小的,因此他们尽量不对可用空间做出假设 - 而是采取给定的大小并尝试做什么说得通。除非您明确地将尺寸限制放在组件上,否则不能保证它们的尺寸。

这意味着,如果LayoutManager不相信它需要调整大小以适应其整体策略,基本上它不会调整它的大小。另一方面,拨打pack是一个明确的要求,可以将所有东西放在一起并消除额外的空间。

+1

这个描述中的细微不正确的假设(据我所知,编辑澄清,如果我在我的理解错误)是一个LayoutManager正在调整_container_它是mananging。它从来不会这样做,而是完全集中在容器的_children_上。在顶层容器中,执行任何大小调整的唯一方法是pack和setSize - 必要时应由应用程序代码调用其中一个。 – kleopatra 2012-01-06 10:32:17

+0

是的,这听起来很准确。 – jefflunt 2012-01-06 14:20:56