首页 > 解决方案 > 为什么我的标签设置为可见时不显示

问题描述

我试图将我的困惑封装在一个最小的程序中。我知道,当将多个组件添加到 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() );
         }
    }
}

标签: javaswing

解决方案


我知道,当将多个组件添加到 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的部分以获取工作示例。


推荐阅读