为什么我的标签如果设置为可见而不显示



我试图用一个最小的程序来封装我的困惑。我知道,当多个组件被添加到JFrame的CENTER区域时,只有最近添加的组件是可见的。但是使用getComponents((,我可以看到以前添加的组件仍然"在那里"。所以我很好奇,为什么在我使用setVisible(false(隐藏最近添加的组件后,我看不到以前添加的部件?非常感谢。

import javax.swing.*;
import java.awt.*;
public class Foo {
public static void main(String [] args) {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
jFrame.setLocationRelativeTo( null );
jFrame.setSize( 300, 300 );
jFrame.setLayout( new BorderLayout() );
// 1. Put 2 JLabels in BorderLayout.CENTER
JLabel label1 = new JLabel( "Label1" ), label2 = new JLabel( "Label2" );
jFrame.add( label1, BorderLayout.CENTER );
jFrame.add( label2, BorderLayout.CENTER );
// 2. Demonstrate that both JLabels are in the JFrame
listAllComponents( jFrame ); // Show that jFrame contains both JLabels.
// 3. Hide the 2nd-added JLabel.
label2.setVisible( false );
label1.setVisible( true );  // WHY IS label1 NOT DISPLAYED?
// 4. Revalidate/repaint the JFrame
jFrame.setVisible( true );
jFrame.revalidate();
jFrame.repaint();
// 5. Why isn't the 1st-added JLabel displayed?
}
// List all of a JFrame's JLabels' text strings (assumes JFrame only contains JLabels).
static void listAllComponents( JFrame jFrame ) {
Component[] components = jFrame.getContentPane().getComponents();
System.out.println( "nComponents in the JFrame:" );
for ( Component component : components ) {
System.out.printf( "t%sn", ((JLabel)component).getText() );
}
}
}

我知道,当多个组件被添加到JFrame的CENTER区域时,只有最近添加的组件是可见的。但是使用getComponents((,我可以看到前面添加的组件仍然"存在">

布局管理器的工作是设置组件的大小和位置。

当框架可见时,将调用布局管理器,并为每个组件指定一个大小和位置。

BorderLayout仅跟踪为每个约束添加的最后一个组件,因此仅设置标签2的大小/位置。

Swing组件的默认大小为(0,0(。由于布局管理器没有更改标签1的大小,因此没有什么可绘制的。

尝试以下操作:

public static void main(String [] args) {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
jFrame.setLocationRelativeTo( null );
jFrame.setSize( 300, 300 );
jFrame.setLayout( new BorderLayout() );
JLabel label1 = new JLabel( "Label1" );
label1.setSize( label1.getPreferredSize() );
JLabel label2 = new JLabel( "Label2" );
jFrame.add( label1, BorderLayout.CENTER );
jFrame.add( label2, BorderLayout.CENTER );
jFrame.setVisible( true );
}

现在,第一个标签有一个大小,所以它被绘制在默认位置,即使布局管理器对此一无所知

如果您确实希望两个组件共享同一空间,则可以使用CardLayout。CardLayout将为所有组件提供一个大小/位置,但它将管理在任何给定时间可见的组件。

阅读Swing教程中关于如何使用CardLayout的部分,以获取一个工作示例。

隐藏组件不会删除它。BorderLayout仍然引用最后一个组件。事实上,在添加了第二个组件之后,BorderLayout并不知道第一个组件。BorderLayout中的组件不"堆叠"。检查BorderLayout:源代码中的字段

/**
* @serial
*/
private Component north;
/**
* @serial
*/
private Component south;
[...]

最新更新