2013-09-07 6 views
1

교체 :의 BorderLayout -의 BorderLayout의 javadoc에서의 BorderLayout 구성 요소

테두리 레이아웃 배치와 5 개 지역에 맞게 그 구성 요소의 크기를 조정하는 컨테이너를 배치 : 북쪽, 남쪽, 동쪽, 서쪽, 그리고 센터. 각 영역에는 하나 이상의 구성 요소가 포함될 수 있으며 해당 상수로 식별되는 입니다 : NORTH, SOUTH, EAST, WEST 및 CENTER.

는 I는 동일한 위치에 다른 버튼을두고 상기의 BorderLayout 센터 버튼을 포함하는 JFrame의 UI가 5 초를 기다린다 생성 another SO question에 기초하여 프로그램을 가지고. .

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 버튼 첫째을 대체 할 기대하지만, 원래의 버튼이 남아있다" "주위를 어슬렁 여기에 코드입니다 첫 번째 버튼은 프레임의 모든 공간을 정식으로 차지합니다. 크기를 조정하면 예상대로 확장됩니다. 지연된 코드가 실행되면 두 번째 버튼이 프레임에 삽입되지만 프레임을 확장하면 두 단추를 볼 수 있습니다. 두 번째 단추는 가운데 구성 요소에 대해 정상적으로 확장되며 첫 번째 단추는 두 번째 단추를 추가 할 때의 크기로 남아 있습니다 (예 : 추가하기 전에 프레임을 확장 한 경우처럼 확장 됨).

광고 후 땡, 두 번째 버튼 위로 마우스를 가져 가면 첫 번째 버튼이 숨겨집니다. 프레임의 크기를 조정하면 첫 번째 프레임의 첫 번째 프레임이 다시 표시됩니다. 첫 번째 버튼이 표시되지 않으면 해당 위치 위로 마우스를 가져 가면 적어도 가끔씩 표시됩니다.

첫 번째 버튼은 여전히 ​​어딘가에 프레임 레이아웃의 일부라는 결론을 내 렸습니다 (예 : 클릭하면 기본 애니메이션이 표시됨). 그러나 어디에서 확인할 수 있습니까? 다른 BorderLayout 구성 요소에없는 코드인지, 그리고 중앙 구성 요소가 실제로 두 번째 단추인지 확인하는 코드가 있습니다.

두 개의 버튼에 대해 동일한 동작을 pack()에 대한 호출 하나와 두 개를 모두 제거했습니다.

원래 질문의 포스터는 두 번째 추가하기 전에 첫 번째 구성 요소를 제거하여 자신의 문제를 해결했지만 첫 번째 단추가이 프로그램에서 계속 참조되는 위치를 알고 싶습니다. 누구든지 도와 줄 수 있습니까?

+2

왜 놀랍습니까? container.add (..) 메소드를 통해 컨테이너에 컴포넌트를 추가하면 명시 적으로 제거 할 때까지 컨테이너의 자식이됩니다. 아이를 관리하는 것은 layoutManager가 아닌 컨테이너의 작업입니다. – kleopatra

+1

한 공간에 여러 구성 요소가있는 경우 [짧은 예제]에서 볼 수 있듯이 ['CardLayout'] (http://docs.oracle.com/javase/7/docs/api/java/awt/CardLayout.html) (http://stackoverflow.com/a/5786005/418556). –

+0

@kleopatra 내가 말했듯이 BorderLayout javadoc은 단 하나의 구성 요소가 그 위치에 살 수 있다는 것을 나타 내기 때문에 놀랍습니다. 따라서 그 위치에 다른 구성 요소를 배치하는 것이 첫 번째 구성 요소를 대체 할 것이라고 생각했습니다. 두 번째가 첫 번째 것을 대체하지 않으면 레이아웃에서 어디에 있습니까? 콘텐츠 창에 있지만 더 이상 레이아웃에 없다고 말하고 있습니까? 동일한 레이아웃 위치에 다른 구성 요소를 추가하면 첫 번째 구성 요소의 고아가 생성되고 '예상'일 가능성이 있지만 괜찮 으면서도 "가장 적은 놀라움의 원칙"을 따르지 않습니다. – arcy

답변

1

나는 클레오 파트라와 앤드류 톰슨의 도움이되는 의견에 주로 근거하여 내 자신의 질문에 답하는 것에 균열을 갖을 것입니다.

BorderLayout 설명서에는 "각 영역에는 하나의 구성 요소 만 포함될 수 있습니다." 분명히 이것을 강제 할 수있는 코드는 없으며 그렇게하는 것은 사용자의 몫입니다.

프로그램의 동작에 대한 가장 좋은 추측은 두 번째 구성 요소가 컨테이너에 추가 될 때 borderlayout의 "가운데"영역 (구성 요소에 대한 자체 참조가 있음)에 제자리에 배치된다는 것입니다. 첫 번째 구성 요소는 여전히 컨테이너에 있지만 레이아웃에는 포함되어 있지 않으므로 여전히 렌더링 될 수 있으며 다른 항목의 위나 아래에 나타날 수 있습니다. 비헤이비어는 레이아웃 컨테이너가 더 이상 관리하지 않기 때문에 실제로 정의되지 않습니다.

저는 이것이 매우 불행하다고 생각합니다. 컴포넌트가 컨테이너에있을 수 있지만 layoutmanager에는 없을 수있는 곳을 가로 지르는 첫 번째 사례입니다. 실제로 처음으로 그러한 것을 고려했습니다. 나는 그것들을 긴밀하게 상호 작용하는 두 대상으로 간주한다. 조정을 도와야한다.

BorderLayout javadoc을 누가 하나의 영역으로 두지 않는지에 대한 사용자의 책임에 대해 언급 할 것을 권고합니다.

+0

반대로 실체적인 증거를 기쁜 표로보고 싶지만, 지금 증거 (및 클레오 파트라의 의견)는 두 번째 추가 두 번째 구성 요소가 컨테이너에 추가됩니다. 그리고 나의 잠은 내가 말할 수있는 한 EDT가 아닌 main()에있다. Container # add는 단일 구성 요소를 포괄적으로 대체 할 수 없으며 FlowLayout과 같은 요소는 전혀 작동하지 않습니다. – arcy