java - 为什么我的标签设置为可见时不显示
问题描述
我试图将我的困惑封装在一个最小的程序中。我知道,当将多个组件添加到 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%s\n", ((JLabel)component).getText() );
}
}
}
解决方案
我知道,当将多个组件添加到 JFrame 的 CENTER 区域时,只有最近添加的组件可见。但是使用 getComponents() 我可以看到之前添加的组件仍然“存在”。
布局管理器的工作是设置组件的大小和位置。
当框架可见时,将调用布局管理器并为每个组件指定大小和位置。
唯一跟踪为每个约束添加的BorderLayout
最后一个组件,因此仅设置 label2 的大小/位置。
Swing 组件的默认大小为 (0, 0)。由于那个布局管理器没有改变 label1 的大小,所以没有什么可以绘制的。
尝试以下操作:
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的部分以获取工作示例。
推荐阅读
- java - 正则表达式从字符串中删除非数字和非小数点
- python - 在 MacOS 上使用 pySerial 读取 RS-232 中的“\xa0”和“\xb”字符
- swift - Swift Vapor - 'Cannot invoke 'add' with a argument list of type ...' configure.swift 中的错误
- tensorflow - 如何在 TensorFlow 2.0 中初始化 LSTM 模型的变量?
- azure - 如何将数组输出分配给逻辑应用变量?
- android - 如何使用 aws ec2 作为 android 应用程序的后端
- swift - RealityKit - 拖动对象切换平面
- php - 如果用户从 Laravel 中的特定路由传递数据,如何仅为控制器中的特定功能禁用中间件
- python - 如何通过名称访问python字典中的项目
- php - PHP 致命错误:未捕获的错误:找不到类 'cake\\lib\\Dispatcher'