1

BorderLayout javadoc から:

ボーダー レイアウトはコンテナーをレイアウトし、そのコンポーネントを配置してサイズを変更し、北、南、東、西、中央の 5 つの領域に収まるようにします。各領域には、複数のコンポーネントを含めることはできず、NORTH、SOUTH、EAST、WEST、および CENTER の対応する定数によって識別されます。

別の SO questionに基づいて、BorderLayout センターにボタンを含む JFrame UI を作成し、5 秒待ってから、別のボタンを同じ位置に配置するプログラムがあります。ステートメント (各領域には複数のコンポーネントが含まれていない可能性があります) があるため、2 番目のボタンが最初のボタンに置​​き換わると予想されます。ただし、元のボタンは「ぶら下がっている」ままです。コードは次のとおりです。

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()); }
        }
    }
}

実行すると、最初のボタンがフレームのすべてのスペースを適切に占有します。サイズを変更すると、期待どおりに拡張されます。遅延コードを実行すると、2 番目のボタンがフレームに配置されますが、フレームを拡大すると両方のボタンが表示されます。2 番目のボタンは、中央コンポーネントの通常どおりに展開されます。最初のボタンは、2 番目のボタンが追加されたときのサイズのままです (たとえば、追加する前にフレームを拡張すると、拡張されます)。

追加後、2 番目のボタンにカーソルを合わせると、最初のボタンが非表示になります。フレームのサイズを変更すると、最初のフレームが 2 番目のフレームの上に再表示されます。最初のボタンが表示されていない場合、その位置にカーソルを合わせると、少なくとも時々表示されます。

最初のボタンはまだフレーム レイアウトのどこかにあると結論付けなければなりません (たとえば、クリックするとデフォルトのアニメーションが表示されます) が、どこにあるのかわかりません。他の BorderLayout コンポーネントのいずれにも含まれていないこと、および中央のコンポーネントが実際に 2 番目のボタンであることを確認するコードがあります。

pack() の 1 つと両方の呼び出しを削除しました - 2 つのボタンに関して同じ動作です。

元の質問の投稿者は、最初のコンポーネントを削除してから 2 番目のコンポーネントを追加することで問題を回避しましたが、このプログラムで最初のボタンがまだ参照されている場所を理解したいと思います。誰でも助けることができますか?

4

2 に答える 2

1

主に kleopatra と AndrewThompson の有益なコメントに基づいて、私自身の質問に答えてみましょう。

BorderLayout のドキュメントには、「各リージョンには 1 つのコンポーネントのみを含めることができる」と記載されています。明らかに、これを強制するコードはなく、それを行うのはユーザー次第です。

プログラムの動作についての私の最善の推測: 2 番目のコンポーネントがコンテナーに追加されると、borderlayout (コンポーネントへの独自の参照を持つ) の「中央」領域に適切に配置されます。最初のコンポーネントはまだコンテナ内にありますが、レイアウト内にはありません。そのため、引き続きレンダリングされ、他のアイテムの上または下に表示される可能性があります。動作は、レイアウト コンテナーによって管理されなくなったため、実際には定義されていません。

これは非常に残念なことだと思います。これは、コンポーネントをコンテナに配置できるが、レイアウトマネージャーに配置できない場所に出くわした最初のケ​​ースであり、実際、そのようなことを考えたのは初めてです。私はそれらを、私が管理する必要がある調整のペアとしてではなく、密接に相互作用する 2 つのオブジェクトと見なします。

2 つのコンポーネントを 1 つの領域に配置しないというユーザーの責任について言及して、BorderLayout の javadoc を強化することをお勧めします。

于 2013-09-07T15:27:13.757 に答える