【问题标题】:Swing components are not visible in custom layout managerSwing 组件在自定义布局管理器中不可见
【发布时间】:2015-10-20 13:46:45
【问题描述】:

我制作了以下布局管理器类:

public class MainFrameLayout extends BorderLayout
{
    private final JPanel north, center, south;

    /**
     * Constructor for this layout.
     */
    public MainFrameLayout()
    {
        super();

        north = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
        center = new JPanel();
        center.setLayout(new BoxLayout(center, BoxLayout.Y_AXIS));
        south = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));

        north.setVisible(true);
        center.setVisible(true);
        south.setVisible(true);

        super.addLayoutComponent(north, NORTH);
        super.addLayoutComponent(center, CENTER);
        super.addLayoutComponent(south, SOUTH);
    }

    @Override
    public void addLayoutComponent(Component comp, Object constraints)
    {
        if (!(constraints instanceof MainFrameLayoutConstraints))
            throw new IllegalArgumentException("Invalid constraints");

        switch ((MainFrameLayoutConstraints) constraints)
        {
            case NORTH:
                north.add(comp);
                break;

            case CENTER:
                center.add(comp);
                break;

            case SOUTH:
                south.add(comp);
                break;
        }
    }
}

MainFrameLayoutConstraints 是一个通用的 enum 类,只有 NORTHCENTERSOUTH 变体。

我尝试在以下应用程序中使用此布局:

public class MyApplication extends JFrame
{
    private final JFormattedTextField caseNumberBox;

    public MyApplication()
    {
        super("A Title Thingy");
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        NumberFormat caseNumberFormat = NumberFormat.getIntegerInstance();
        caseNumberBox = new JFormattedTextField(caseNumberFormat);
        caseNumberBox.setColumns(20);

        this.setLayout(new MainFrameLayout());
        this.add(new JLabel("Major Release Case: "), MainFrameLayoutConstraints.NORTH);
        this.add(caseNumberBox, MainFrameLayoutConstraints.NORTH);

        this.pack();
        this.setVisible(true);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        MyApplication app = new MyApplication();
    }
}

为什么,当我运行这个应用程序时,我的组件(标签和文本字段)是不可见的,即使对 pack() 的调用适当地调整了窗口大小以适合这些字段?

【问题讨论】:

  • 为什么要创建这样的布局管理器?只是不要使用 EAST,WEST 约束。是否在 switch 语句中添加了调试代码以查看代码是否正在执行?
  • 必须执行代码才能适当调整主框架的大小。如果我在MyApplication 构造函数中删除对add() 的调用,则框架的大小将不再合适。组件正在添加但未保留。我做了一些调试代码来设置面板的背景颜色,但没有出现任何颜色。这让我相信在框架变得可见之前面板就被移除了。
  • 无需创建自定义布局管理器。只需使用 BorderLayout 的默认实现将组件添加到框架中。
  • 目前这更像是一种教育。我只是想知道他们为什么走了。我已经使用自定义面板实现了我想要的界面,但我仍然想了解为什么这段代码行为不正确。
  • LayoutManager 不会创建组件或将组件添加到面板。 LayoutManager 仅将约束与组件相关联,因此当 LayoutManager 确定已使用布局管理器添加到面板的组件的大小/位置时,可以使用约束。您不能只创建自己的“MainFrameLayoutConstraints”,因为所有布局管理器代码都需要一个字符串约束。如果您想限制约束,那么您所能做的就是更改编辑以确保字符串为“North”、“South”或“Center”。

标签: java swing awt layout-manager border-layout


【解决方案1】:

该行为的原因是试图在布局管理器中创建组件。虽然MainFrameLayout 为其创建的组件调用super.addLayoutComponent(),但这些组件添加到父组件本身。因此,您添加到帧计数以计算帧的首选大小的组件,因为它被委托给BorderLayout,它假定内容窗格包含您在MainFrameLayout 构造函数中创建的面板,但它们永远不会被绘制,因为面板没有' t 实际上已添加到内容窗格中。

自定义布局管理器不是您想要实现的目标的错误工具。只需使用嵌套布局。

【讨论】:

    【解决方案2】:

    评论员是这么说的。您的自定义布局并不是真正需要的。您可以直接在 MyApplication 类中添加组件。

    public MyApplication() {
        ...
        setLayout(new BorderLayout(2, 1));
        ...            
        add(new JLabel("Major Release Case: "), BorderLayout.NORTH);
        add(caseNumberBox, BorderLayout.CENTER);            
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-11
      • 1970-01-01
      • 2011-05-23
      • 2011-09-13
      • 1970-01-01
      相关资源
      最近更新 更多