2010-12-08 5 views
4

GroupLayout을 사용하여 이상한 동작을 관찰하고 있습니다. JFrame의 크기를 조정하고 다른 구성 요소를 밀어내는 JScrollPane 내부에 포함 된 JTextArea가 있습니다. 이상하게도 레이아웃을 재정렬하면 JTextArea가 위 또는 아래에 아무런 차이가 없으므로 (아무런 간격도 없음) 잘 동작합니다. 마치 텍스트 영역에서 컨테이너에 얼마나 많은 공간이 있는지 묻는 것입니다. 그런 다음 다른 구성 요소와 상관없이 100 % 차지합니다. 또 다른 이상한 점은 JTextArea (JScrollPane 아님) 크기와 컨테이너 내의 다른 컴포넌트 높이가 Short.MAX_VALUE에 도달 할 때만 발생하는 것처럼 보입니다.JTextArea가 GroupLayout의 프레임을 오버플로하는 이유는 무엇입니까?

스크롤 창 (레이아웃에 구성 요소를 추가 할 때)의 세로 그룹에서 최대 크기를 Short.MAX_VALUE보다 작은 값으로 지정하면 문제가 해결되는 것 같습니다. 값과 Short.MAX_VALUE가 다른 기타 구성 요소의 높이보다 큽니다. 예 : 나는 작은 양의 값을 대신 GroupLayout.PREFERRED_SIZE 또는 GroupLayout.DEFAULT_SIZE의 추천 사이즈를 설정하면

.addComponent(textArea, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE - 500)

또한, 또한이 동작은 멀리 갈 수 있도록 보인다. 예 :

.addComponent(textArea, 0, 1, Short.MAX_VALUE)

GroupLayout의 자바 튜토리얼 이에 대해 아무것도 언급하는 것 그리고 사방에 Short.MAX_VALUE에 사용하는 경향하지 않습니다. Google 검색을 사용하여 답변을 찾았지만이 문제를 검색어로 설명하기가 매우 어려웠습니다.

버그를 발견 했습니까? 또는 GroupLayout을 이해하지 못 했습니까? 후자가 분명히 더 많이 보인다.

이 예제는 간단한 텍스트 영역을 만듭니다. 아래쪽 버튼을 눌러 텍스트로 채 웁니다 (그리고 JScrollPane 내부의 JTextArea 크기를 조정합니다). 그런 다음 텍스트 영역 내부를 클릭하고 선을 추가하거나 제거 할 수 있습니다. 추가 선을 추가 한 후 다시 그리기 버튼을 클릭하거나 프레임의 크기를 조절하여 이상한 동작을 확인합니다.

public class GroupLayoutTest { 
    public GroupLayoutTest() { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       final JFrame frame = new JFrame("GroupLayout test"); 
       Container panel = frame.getContentPane(); 

       GroupLayout layout = new GroupLayout(panel); 
       panel.setLayout(layout); 

       JButton addBtn = new JButton("Add Lines"); 
       JButton redrawBtn = new JButton("Redraw"); 

       final JTextArea textArea = new JTextArea(); 
       final JScrollPane textPane = new JScrollPane(textArea); 

       layout.setHorizontalGroup(layout.createParallelGroup() 
         .addComponent(redrawBtn) 
         .addComponent(textPane) 
         .addComponent(addBtn)); 

       layout.setVerticalGroup(layout.createSequentialGroup() 
         .addComponent(redrawBtn) 
         .addComponent(textPane) 
         .addComponent(addBtn)); 

       addBtn.addActionListener(new ActionListener() { 
        int m = 0; 

        @Override 
        public void actionPerformed(ActionEvent e) { 
         for (int i = m; m < i + 2044; ++m) { 
          textArea.append("Line " + m + "\n"); 
         } 

         // redraw the frame 
         frame.validate(); 
        } 
       }); 

       redrawBtn.addActionListener(new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         frame.validate(); 
        } 
       }); 

       frame.setPreferredSize(new Dimension(640, 480)); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static void main(String[] args) { 
     new GroupLayoutTest(); 
    } 
} 
+0

1 : 여기

는 (그것은 또한 빌더를 가지고 있지만,이 경우에는 내가 쉽게 열을 걸쳐 셀 제약 조건을 사용하고 있습니다) FormLayout에 어떻게 보일지입니다 sscce.org/ –

답변

1

나는 GroupLayout의 내부를 잘 모르겠지만, 일반적으로는 레이아웃 매니저에게 작업 할 몇 가지 정보를 제공하는 텍스트 영역/스크롤 콤보의 바람직한 크기를 지정해야합니다.

final JTextArea textArea = new JTextArea(10, 30); 

또는

textPane.setPreferredSize(new Dimension(400, 200)); 

그렇지 않으면 내가 선호하는 크기는 기본적으로 텍스트 영역에 추가 된 모든 텍스트의 크기 생각이이 중 하나를 사용하여 수행됩니다.

+0

당신 말이 맞아서 당신의 제안이 문제를 해결하는 것 같습니다; 그러나 텍스트 영역이 매우 커지지 않는 한이 작업은 필요하지 않습니다. 이러한 변경 사항이 없으면 기본 크기가 정확하며 텍스트 영역이 "작음"으로 예상되는대로 모든 것이 표시됩니다. 그러면 답이 아니라 회피책처럼 느껴집니다. – jigawot

+1

@jigawot, 해결 방법이 아닙니다. 레이아웃 관리자가 작동하는 방식입니다. 텍스트 영역이 작동하는 방식입니다. FlowLayout을 사용하여 텍스트 영역을 패널에 추가하고 입력을 시작하면 어떤 일이 발생하는지 볼 수 있습니다. 텍스트 영역 크기는 계속 변경되는 텍스트를 기반으로 변경됩니다. 구성 요소에 대해 고정 된 선호 크기를 사용하여 GUI를 설계해야합니다. 프레임에 설정된 기본 크기를 사용하지 않아야합니다. pack() 메서드가 크기를 결정하도록해야합니다. 요구 사항에 따라 필요한 수의 행과 열을 가진 텍스트 영역을 정의해야합니다. 더 쉬운 BorderLayout을 사용하십시오. – camickr

+0

당신은 매우 유효한 포인트를 만들었지 만, 나는 정중하게 반대해야합니다. 당신은 FlowLayout을 사용하여 당신의 포인트를 보여 주면서 언급하고 있습니다. 이것이 내가 얻는 것의 대표적인 예입니다 : FlowLayout을 사용한다면, 당신은 * 바람직한 크기를 지정해야합니다. 그렇지 않으면 제대로 작동하지 않습니다. GroupLayout을 사용하면 (자), Short.MAX_VALUE에 접근 할 때까지, 적절한 사이즈를 추측 해 훌륭한 일을 할 수 있습니다. 이 이상한 행동은 내 질문의 근원이며, 내가 찾는 대답 대신 회신이 해결 방법이라고 느끼는 이유는 무엇입니까? 내 질문은 "왜?" "수정 방법"이 아닌 – jigawot

2

저는 GroupLayout에 익숙하지 않습니다. 이것은 내가 문서를보고 그것에 대해 생각한 것입니다. 잘하면 도움이됩니다. 내 대답은 오래 걸려서 위로 요약 해 보겠습니다.

왜 이런 일이 발생합니까? 3 가지의 조합.

  1. GroupLayout은 구성 요소의 기본 크기를 고려합니다. (귀하가 귀하의 의견에 따라 판단한 이유입니다).
  2. 귀하의 수직 그룹은 순차적입니다. 선호하는 크기로 한 번에 하나의 구성 요소를 배치하거나 여유 공간이 있으면 더 크게 배치합니다.
  3. JScrollPane에는 제한없는 기본 크기가 있습니다.JTextArea의 선호 크기가 어떤 것이 든간에 점점 커지고 있습니다. 선호하는 크기가 프레임의 크기보다 커지면 그 아래의 구성 요소를위한 공간을 남기지 않습니다.

매우 큰 선호 크기의 구성 요소와 기본 크기를 고려한 레이아웃 관리자를 결합하면 일반적으로 항상이 문제가 발생합니다. 광범위하게 테스트하지는 않았지만, FormLayout에서도 (원하는 크기를 사용한다고 말한 경우) 이런 일이 발생한다는 것도 알고 있습니다.

설명/사고 과정에서

긴 시도 :

텍스트 영역이 얼마나 많은 공간 용기에, 그리고 그것의 100 %를 가지고있다 컨테이너를 요청하는 것처럼이 에 관계없이 다른 구성 요소.

텍스트 영역은 컨테이너가 얼마나 큰지를 묻지 않습니다. 반대쪽입니다. 컨테이너의 크기를 알려주고 있습니다. 이 경우 textArea는 스크롤 창에 직접 포함됩니다. 텍스트 영역의 기본 크기는 텍스트 영역의 텍스트 크기에 따라 커질 것입니다. 스크롤 창에서 원하는 크기를 설정하지 않으면 스크롤 영역의 기본 크기가 텍스트 영역의 기본 크기와 함께 커집니다. 거기에서, 레이아웃 관리자는 물건을 놓는 방법을 결정할 것입니다.

이 경우 수직 레이아웃에 대해 SequentialGroup과 함께 GroupLayout을 사용하고 있습니다. 이것은 최소/pref/max 크기를 기준으로 구성 요소를 순서대로 배치합니다. textPane의 위치를 ​​그룹의 마지막 항목으로 변경하면 다른 구성 요소의 공간을 훔치지 않을 것입니다. 매우 큰 크기의 경우 GroupLayout은 모든 구성 요소가 표시되는지 상관하지 않습니다. if 마지막 구성 요소 다음에 남은 공간이 없으므로 컨테이너가 확대 될 때까지 표시되지 않습니다. 작은 크기의 경우 사용자가 프레임 크기를 조정할 수 있지만 예제와 같이 큰 크기의 경우에는 적합하지 않습니다.

누락과는 별도로 - 거대한 스크롤 창과 GroupLayout의 조합은 멈추는 시점을 알 수 없으므로 ... 스크롤 창 바의 아래 부분이 잘릴 수 있습니다. @camickr가 제시 한대로 JScrollPane에 적절한 크기를 설정하는 것으로 피할 수 있습니다.

다른 이상한 것은

는 일이 를 나타납니다 경우에만 JTextArea에 (하지 JScrollPane의) 사이즈에 용기 도달 Short.MAX_VALUE에 내의 다른 구성 요소 높이.

각 구성 요소의 크기를 로그 아웃하면 JScrollPane의 기본 크기를 지정하지 않으면 항상 기본 크기가 textArea보다 더 크기 때문에 표시되지 않습니다. 위의 진술이 사실이라고 생각하십시오. 스크롤 창 크기와 컨테이너의 다른 구성 요소는 여전히 Short.MAX_VALUE를 초과하며 GroupLayout에서 문제가되는 것으로 보입니다.

JScrollPane의 포인트는 포함 된 더 작은 영역 (적절한 경우 스크롤 막대 포함)에 큰 (또는 잠재적으로 큰) 기본 크기가있는 구성 요소를 저장하는 것입니다. 그런 다음 스크롤 패널을 원하는 크기보다 크게 늘릴 수는 있지만 스크롤 창에 표시 할 크기를 알려주는 것으로 시작합니다. 실제로, 적절한 사이즈를 설정하면 (자), 스크롤 바를 필요로 할 때 JScrollPane에 효과적으로 통지 할 수 있습니다. 예를 들어, 스크롤 구획의 적절한 사이즈가 400,300의 경우, 포함되는 컴퍼넌트의 적절한 폭이 400 (또는 스크롤 구획의 사이즈가 바람직한 사이즈보다 커지는 컨테이너 내에있는 경우)을 초과 할 때마다, , 가로 스크롤 막대를 표시하십시오. 마찬가지로, 높이도 마찬가지입니다.그렇지 않으면 항상 당신이 가지고있는 것의 크기로 커질 것이고, 스크롤 바를 필요로하지 않으며, 포인트를 없애거나, 어떤 경우에는 다른 컴포넌트가 보이지 않게 할 것입니다.

GroupLayout에 대한 문서는 일반적으로 다른 레이아웃 빌더 도구에서 사용되며 일반적으로 개발자가 아니라 (아직까지는 가능하지만). 내가 정상적으로 작동하도록 특별한 최대 값을 사용해야한다는 것을 다른 레이아웃을 사용하는 것을 고려할 것이다. 개인적으로 가장 좋아하는 프로그램은 FormLayout이며 무료 BSD 라이센스 타사 레이아웃 관리자입니다. 나는 정상적인 구성 요소에 대해 고정 된 크기를 지정해야한다고 생각하지 않지만, 스크롤 창의 경우 원하는 크기를 고려한 레이아웃에서 원하는 크기를 지정하려고합니다.

모든 레이아웃이 DPI를 존중하고, 적절한 위치에서 성장하며, 국제화 (텍스트 길이가 매우 다른 경우) 작업이 잘되기를 바란다. 그래서 모든 것에 대해 고정 크기를 지정해야하는 것은 사용하고 싶지 않다. . 대부분의 레이아웃에서 스크롤 창에 고정 된 기본 크기를 설정하는 것이 좋지 않다고 생각합니다. 단추, 텍스트 필드 또는 분명히 선호되는 크기를 가진 다른 구성 요소를 그렇게 많이하지는 않습니다. // : HTTP - SSCCE에 대한

FormLayout layout = new FormLayout(
     "pref,fill:pref:grow", // cols 
     "pref,3dlu,fill:pref:grow,3dlu,pref" // rows 
); 

JPanel panel = new JPanel(layout); 

CellConstraints cc = new CellConstraints(); 

panel.add(redrawBtn, cc.xy(1, 1)); 
panel.add(textPane, cc.xyw(1, 3, 2)); // span 2 columns 
panel.add(addBtn, cc.xy(1, 5)); 

frame.setContentPane(panel); 
+0

우선, 자세한 설명에 감사드립니다. 나는 전에 FormLayout을 보지 않았으며 확실히 살펴볼 것입니다. 스크롤 창의 기본 크기에 대한 의견을 따르지 않을지 잘 모르겠습니다. 크기를 기록 할 때 스크롤 영역의 기본 크기는 텍스트 영역이 매우 커지는 동안 프레임 (393px)에 맞는 크기 일뿐입니다. 텍스트 영역의 기본 크기가 약 32700이되면 스크롤 창의 기본 크기가 커지고 다른 구성 요소가 프레임에서 빠져 나옵니다. – jigawot

+0

또한 스크롤 창의 기본 크기를 우회적 인 값 (예 : 1 픽셀)으로 명시 적으로 설정하면 GroupLayout은 해당 구성 요소의 크기를 393 픽셀로 적절하게 지정하고 내부에 포함 된 텍스트 영역이 커지면 스크롤 창 프레임 밖에서 아무 것도 누르지 않고 393 픽셀로 바로 유지됩니다.이것은 나에게 매우 이상하게 보인다. – jigawot

+0

흥미 롭습니다. 내 경우, 내가 한 일은 패널에 "다시 그리기"버튼을 놓고 각 구성 요소의 최소, 선호 및 최대 크기를 인쇄하는 "정보"버튼을 던집니다. 아마도 패널에 영향을 미쳤을 것입니다. 또는 Java 버전 및/또는 플랫폼의 차이점이 있습니까? 난 단지 당신의 다시 그리기 버튼의 액션 코드를 교체하고 그 밖의 모든 것을 남겨 두어 테스트했습니다. 그리고 scrollpane의 선호 크기는 언급 한대로 확실히 증가하고 있습니다. 나는 Java 1.6.0_21, Windows 7 btw –

관련 문제