繁体   English   中英

BorderLayout — 替换 BorderLayout 组件

[英]BorderLayout — replacing BorderLayout component

来自 BorderLayout javadoc:

边框布局布局一个容器,排列和调整其组件的大小以适应五个区域:北、南、东、西和中心。 每个区域可能包含不超过一个组件,并由相应的常量标识:NORTH、SOUTH、EAST、WEST 和 CENTER。

我有一个基于另一个 SO question 的程序,它创建一个 JFrame UI,其中包含 BorderLayout 中心的一个按钮,等待 5 秒,然后在同一位置放置一个不同的按钮。 由于声明(每个区域可能包含不超过一个组件”,我希望第二个按钮替换第一个。但是,原始按钮仍然“徘徊”。这是代码:

import java.awt.BorderLayout;
import java.awt.Component;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class ReplaceBorderLayoutComponent extends JFrame
{
  private static final long serialVersionUID = 1L;

  public static void say(String msg) { System.out.println(msg); }

    public void createUI()
    {
      setDefaultCloseOperation(DISPOSE_ON_CLOSE);
      try
      {
        SwingUtilities.invokeAndWait
        (
            new Runnable()
            {
              public void run()
              {
//                setLayout(new BorderLayout());
                JButton longText = new JButton("Quite a long text");
                /*getContentPane().*/add(longText, BorderLayout.CENTER);
                pack();
                setVisible(true);
                say("longText = " + longText.toString());
              }
            }
        );
      }
      catch (Exception e) {}
    }

    public void replaceComponent()
    {
      try
      {
        SwingUtilities.invokeAndWait
        (
            new Runnable()
            {
              public void run()
              {
                JButton anotherText = new JButton("Another text");
                /*getContentPane().*/add(anotherText, BorderLayout.CENTER);
                pack();
                validate();
                repaint();
                say("anotherText = " + anotherText.toString());
              }
            }
        );
      }
      catch (Exception e)      {      }
      say("replaced");
    }

    public Component getComponent(String constraint)
    {
      BorderLayout bl = (BorderLayout)getContentPane().getLayout();
      return bl.getLayoutComponent(constraint);
    }

    public static void main(String ... args) 
    { 
        ReplaceBorderLayoutComponent st = new ReplaceBorderLayoutComponent();
        st.createUI();
        try { Thread.sleep(5000); } catch (InterruptedException ie) {}
        st.replaceComponent();
        Component c = st.getComponent(BorderLayout.CENTER);
        say("Center component = " + c.toString());

        String otherPlaces[] = { "North", "South", "East", "West", "First", "Last", "Before", "After" };
        for (String s : otherPlaces)
        {
          Component c2 = st.getComponent(s);
          if (c2 != null) { say("found additional component at " + s + ", " + c2.toString()); }
        }
    }
}

当我运行它时,第一个按钮适当地占据了框架的所有空间。 如果我调整它的大小,它会按预期扩展。 当延迟代码运行时,它将第二个按钮放在框架中,但如果我展开框架,我可以看到两个按钮。 第二个按钮像中心组件一样正常展开; 第一个按钮保持添加第二个按钮时的大小(例如,如果我在添加之前扩展框架,则会扩展)。

添加后,将鼠标悬停在第二个按钮上会隐藏第一个; 调整框架大小会在第二个顶部重新显示第一个。 如果第一个按钮不可见,将鼠标悬停在其位置上会显示它,至少有时是这样。

我必须得出结论,第一个按钮仍然是某处框架布局的一部分(例如,它显示被点击时的默认动画),但我不知道在哪里。 我有代码来确保它不在任何其他 BorderLayout 组件中,并且中心组件确实是第二个按钮。

我删除了对 pack() 的一个和两个调用 - 两个按钮的行为相同。

原始问题的发布者通过在添加第二个组件之前删除第一个组件来解决他的问题,但我想了解第一个按钮在此程序中仍被引用的位置。 任何人都可以帮忙吗?

我将尝试回答我自己的问题,主要基于 kleopatra 和 AndrewThompson 的有用评论。

BorderLayout 文档说“每个区域可能只包含一个组件”; 显然没有代码可以强制执行此操作,这取决于用户。

我对程序行为的最佳猜测:当第二个组件添加到容器中时,它会适当地放置在边框布局的“中心”区域(它有自己对组件的引用)。 第一个组件仍在容器中,但不在布局中,因此它仍然可以被渲染并且可能出现在其他项目的顶部或下方; 行为并未真正定义,因为它不再由布局容器管理。

我认为这很不幸; 这是我遇到的第一个组件可以在容器中但不在 layoutmanager 中的情况,实际上这是我第一次考虑这样的事情。 我将它们视为两个密切交互的对象,而不是我需要帮助管理其协调的一对。

如果我知道向谁推荐它,我会建议加强 BorderLayout javadoc,并提及用户有责任不要将两个组件放入一个区域。

我有同样的问题。 我放弃了BorderLayout而是使用了JInternalFrame JInternalFrameJFrame内部创建一个JFrame 它可以使用setContentPane()替换其所有组件,然后刷新它。

import java.awt.*;
import java.swing.*;

JFrame F = new JFrame();
JInternalFrame f = new JInternalFrame();

//Build outer frame
F.setBounds(100, 100, 500, 500);
F.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
F.getContentPane().setLayout(null);

//Build inner frame
f.setVisible(true);
f.setBounds(120, 120, 120, 120);
F.add(f);

//Replace content of inner frame
f.setContentPane(JComponent);
f.revalidate();
f.repaint();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM