首页 文章

BorderLayout - 替换BorderLayout组件

提问于
浏览
1

来自BorderLayout javadoc:

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

我有一个基于another SO question的程序,它在BorderLayout中心创建一个包含按钮的JFrame UI,等待5秒,然后将不同的按钮放在相同的位置 . 由于声明(每个区域可能包含不超过一个组件", I would expect the 2nd button to replace the first. However, the original button remains "挂在“ . 这是代码:

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() - 相对于两个按钮的相同行为 .

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

1 回答

  • 1

    我主要根据kleopatra和AndrewThompson的有用评论来回答我自己的问题 .

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

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

    我觉得这很不幸;这是我遇到的第一个案例,一个组件可以在容器中但不在布局管理器中,事实上它是我第一次考虑这样的事情 . 我认为它们是两个密切相互作用的对象,而不是一对我需要帮助管理的协调 .

    我建议使用BorderLayout javadoc,并提及用户有责任不将两个组件放入一个区域,如果我知道该建议的话 .

相关问题