Java Swing에서 set (Preferred | Maximum | Minimum) Size 메서드를 사용하지 않아야합니까?


481

여러 번 다음 방법의 사용을 제안한 것에 대해 비판을 받았습니다.

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

Swing구성 요소. 표시된 구성 요소 간의 비율을 정의하려는 경우 사용에 대한 대안이 없습니다. 나는 이것을 들었다 :

레이아웃의 대답은 항상 동일합니다. 적절한 LayoutManager를 사용하십시오.

웹을 조금 검색했지만 주제에 대한 포괄적 인 분석을 찾지 못했습니다. 그래서 다음과 같은 질문이 있습니다.

  1. 그 방법의 사용을 완전히 피해야합니까?
  2. 방법은 이유에 의해 정의되었습니다. 언제 사용해야합니까? 어떤 맥락에서? 어떤 목적으로?
  3. 이러한 방법을 사용하면 어떤 부정적인 결과가 발생합니까? (화면 해상도가 다른 시스템간에 이식성을 추가하는 것만 생각할 수 있습니다).
  4. LayoutManager가 원하는 모든 레이아웃 요구를 정확하게 충족시킬 수 있다고 생각하지 않습니다. 레이아웃의 작은 변형마다 새로운 LayoutManager를 구현해야합니까?
  5. 4에 대한 대답이 "예"이면 LayoutManager 클래스가 확산되어 유지 관리가 어려워지지 않습니까?
  6. Component의 자식들 사이에 비율을 정의해야하는 상황에서 (예를 들어, child1은 공간의 10 %, child2 40 %, child3 50 %를 사용해야 함), 사용자 정의 LayoutManager를 구현하지 않고도 달성 할 수 있습니까?

답변:


236
  1. 그 방법의 사용을 완전히 피해야합니까?

    응용 프로그램 코드의 경우 예

  2. 방법은 이유에 의해 정의되었습니다. 언제 사용해야합니까? 어떤 맥락에서? 어떤 목적으로?

    나는 개인적으로 그것을 API 디자인 사고라고 생각합니다. 어린이 크기에 대한 특별한 아이디어가있는 복합 구성 요소에 의해 약간 강제됩니다. 사용자 정의 LayoutManager로 요구 사항을 구현 했어야했기 때문에 "약간"입니다.

  3. 이러한 방법을 사용하면 어떤 부정적인 결과가 발생합니까? (화면 해상도가 다른 시스템간에 이식성을 추가하는 것만 생각할 수 있습니다.)

    일부 (불완전하고 불행하게도 SwingLabs를 java.net으로 마이그레이션하여 링크가 끊어짐) 기술적 이유는 예를 들어 규칙 (hehe) 또는 내 답변에 대한 의견에서 찾은 @bendicott 링크에 언급되어 있습니다. 사회적으로, 코드를 유지해야하며 깨진 레이아웃을 추적해야하는 불행한 동료에게 수많은 작업을합니다.

  4. LayoutManager가 원하는 모든 레이아웃 요구를 정확하게 충족시킬 수 있다고 생각하지 않습니다. 레이아웃의 작은 변형마다 새로운 LayoutManager를 구현해야합니까?

    예, "모든 레이아웃 요구"에 대한 아주 좋은 근사치를 충족 할 수있을만큼 강력한 LayoutManager가 있습니다. 큰 세 가지는 JGoodies FormLayout, MigLayout, DesignGridLayout입니다. 실제로 실제로는 고도로 전문화 된 환경을 제외하고는 LayoutManager를 작성하는 경우가 거의 없습니다.

  5. 4에 대한 대답이 "예"이면 LayoutManager 클래스가 확산되어 유지 관리가 어려워지지 않습니까?

    (4의 대답은 "아니오"입니다.)

  6. 구성 요소의 자식 사이에 비율을 정의 해야하는 상황에서 (예를 들어, 자식 1은 공간의 10 %, 자식 2 40 %, 자식 3 50 %를 사용해야 함) 사용자 정의 LayoutManager를 구현하지 않고도 달성 할 수 있습니까?

    모든 Big-Three는 GridBag조차도 할 수 없습니다.


4
나는 적어도 두 가지 상황 에서이 조언에 동의한다고 확신하지 않습니다. 1) 사용자 정의 렌더링 구성 요소 2) JEditorPane자체 너비를 제안하지 않는 with with HTML 사용 . OTOH 내가 놓친 것이 확실하지 않습니다. 스레드의 답글을주의 깊게 검토하지만 특히 후자의 경우 의견이 있으면 관심이있었습니다.
Andrew Thompson

2
@Andrew Thompson 1) 사용자 지정 구성 요소 : 유용한 레이아웃 힌트를 반환하는 것은 comp 자체입니다. impl이 버그가없는 경우 2) 핵심 comp도 버그가 있습니다 .-) 3) 공백은 신경 쓰지 않습니다. 이번에 고의로 감사드립니다 :-)
kleopatra

8
허용되는 답변이 setXXX () 메서드를 사용하지 말라고 대답 할 수는 없습니다. 때로는 레이아웃 관리자에게 힌트를 제공하기 위해 단순히 필요합니다. 패널을 배치하는 경우 필요할 때 이러한 방법을 자유롭게 사용할 수 있습니다. 적절한 레이아웃 관리자를 사용하면 이러한 방법이 자주 필요하지 않지만 때로는 필요할 때가 있다고 생각합니다. X_AXIS BoxLayout에 JComboBox 또는 JSpinner를 넣고 사용하지 마십시오 .setMaximumSize ()가 필요하다고 생각합니다.
Michael

5
@Michael 아니오, 나는 절대적으로 필요하지 않습니다-대답은 항상 적절한 LayoutManager를 사용하고 관리자 수준 (vs. 구성 요소 수준) 에서 미세 조정을 수행하는 것입니다.
kleopatra

5
스택 오버 플로우에서 "괜찮은 LayoutManager를 사용하고 원하는 크기를 지정하십시오"라고 계속 말하지만 "괜찮은"LayoutManager의 특정 예제는 제공하지 않습니다. 그리고 어떤 표준 관리자도 직접 크기를 제어 할 수 없습니다.
Ti Strga

100

몇 가지 휴리스틱 :

  • 여기 에 표시된대로 고유 한 구성 요소를 만들 때와 같이 set[Preferred|Maximum|Minimum]Size()재정의하려는 경우 사용하지 마십시오 .get[Preferred|Maximum|Minimum]Size()

  • 여기 및 아래에 표시된대로 set[Preferred|Maximum|Minimum]Size()구성 요소의 신중하게 재정의 된 구성 요소에 의존 할 수있는 경우 사용하지 마십시오 .getPreferred|Maximum|Minimum]Size

  • 아래 및 여기에 표시된대로 set[Preferred|Maximum|Minimum]Size()사후 validate()형상 을 도출 하는 데 사용 하십시오 .

  • 예를 들어 구성 요소에 원하는 크기가없는 경우 JDesktopPane컨테이너의 크기를 조정해야 할 수도 있지만 이러한 선택은 임의적입니다. 의견은 의도를 명확히하는 데 도움이 될 수 있습니다.

  • 주석 에서 언급 한 것처럼 파생 된 크기를 얻기 위해 많은 구성 요소를 반복해야하는 경우 대체 또는 사용자 정의 레이아웃을 고려하십시오 .

여기에 이미지 설명을 입력하십시오

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * @see /programming/7229226
 * @see /programming/7228843
 */
public class DesignTest {

    private List<JTextField> list = new ArrayList<JTextField>();
    private JPanel panel = new JPanel();
    private JScrollPane sp = new JScrollPane(panel);

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                DesignTest id = new DesignTest();
                id.create("My Project");
            }
        });
    }

    private void addField(String name) {
        JTextField jtf = new JTextField(16);
        panel.add(new JLabel(name, JLabel.LEFT));
        panel.add(jtf);
        list.add(jtf);
    }

    private void create(String strProjectName) {
        panel.setLayout(new GridLayout(0, 1));
        addField("First Name:");
        addField("Last Name:");
        addField("Address:");
        addField("City:");
        addField("Zip Code:");
        addField("Phone:");
        addField("Email Id:");
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
            .addPropertyChangeListener("permanentFocusOwner",
            new FocusDrivenScroller(panel));
        // Show half the fields
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        sp.validate();
        Dimension d = sp.getPreferredSize();
        d.setSize(d.width, d.height / 2);
        sp.setPreferredSize(d);

        JInternalFrame internaFrame = new JInternalFrame();
        internaFrame.add(sp);
        internaFrame.pack();
        internaFrame.setVisible(true);

        JDesktopPane desktopPane = new JDesktopPane();
        desktopPane.add(internaFrame);

        JFrame frmtest = new JFrame();
        frmtest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmtest.add(desktopPane);
        frmtest.pack();
        // User's preference should be read from java.util.prefs.Preferences
        frmtest.setSize(400, 300);
        frmtest.setLocationRelativeTo(null);
        frmtest.setVisible(true);
        list.get(0).requestFocusInWindow();
    }

    private static class FocusDrivenScroller implements PropertyChangeListener {

        private JComponent parent;

        public FocusDrivenScroller(JComponent parent) {
            this.parent = parent;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Component focused = (Component) evt.getNewValue();
            if (focused != null
                && SwingUtilities.isDescendingFrom(focused, parent)) {
                parent.scrollRectToVisible(focused.getBounds());
            }
        }
    }
}

2
"외부 요소"에 의한 추론에 대해 (당신이 짐작할 수 있듯이 :-) 동의하지 않음 : XXSize 특성은 내부 요구 표현하기위한 것입니다. 외부에서 사람들을 조정하는 것은 잘못 사용하여 일명 해킹입니다. 만약 당신이 그것을 선호하는 특정 크기의 (내장 또는 J) 프레임을 원한다면 ... 프레임이 아닌 내용의 크기를 정하십시오
kleopatra

2
@ kleopatra : 조금만 강박하십시오 : setXXSize 메소드를 외부에서 절대 사용해서는 안되는 이유는 무엇입니까? 디자인이 부족하지 않습니까? 공개 수정자가 암시 적으로 사용자에게 해당 메소드를 사용할 수 있다고 말하지 않습니까?
Heisenbug

2
@kleopatra에 동의해야합니다 : setPreferredSize()항상 구성 요소의 계산을 임의의 선택으로 바꿉니다.
trashgod

1
@trashgod 당신에게 100은 내가 그들을 호출 (만의 것은 물론이 사용자 정의 구성 요소가 이렇게 좋을 것 오버라이드 (override)가 의미)도, 이러한 메소드를 오버라이드 (override)에 문제가없는 생각
데이비드 Kroukamp

5
@DavidKroukamp : 감사합니다. 나는 kleopatra의 더 큰 경험을 미루고 있지만, 반대 견해를 비판적으로 검토 할 때 가치가 있다고 생각합니다.
trashgod

47

그 방법의 사용을 완전히 피해야합니까?

아니요, 이러한 메서드를 호출하거나 재정의하는 것이 허용되지 않는다는 공식적인 증거는 없습니다. 실제로 오라클은 이러한 방법이 크기 힌트를 제공하는 데 사용된다고 말합니다 ( http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment) .

사용자 지정 구성 요소 인스턴스에서 메서드를 호출하지 않고 Swing 구성 요소를 확장 할 때 재정의 될 수도 있습니다 (Swing의 모범 사례 ).

구성 요소의 크기를 어떻게 지정하더라도 구성 요소의 컨테이너는 요청 된 구성 요소의 크기를 고려한 레이아웃 관리자를 사용해야합니다.

방법은 이유에 의해 정의되었습니다. 언제 사용해야합니까? 어떤 맥락에서? 어떤 목적으로?

구성 요소가 잘 배치되도록 컨테이너 레이아웃 관리자에 사용자 정의 크기 힌트를 제공해야하는 경우

이러한 방법을 사용하면 어떤 부정적인 결과가 발생합니까? (화면 해상도가 다른 시스템간에 만 이식성을 추가 할 수 있다고 생각합니다).

  • 많은 레이아웃 관리자는 구성 요소의 요청 된 최대 크기에주의를 기울이지 않습니다. 그러나, BoxLayoutSpringLayout않습니다. 또한 GroupLayout구성 요소를 건드리지 않고 최소, 기본 또는 최대 크기를 명시 적으로 설정할 수 있습니다.

  • 구성 요소의 정확한 크기를 설정해야합니다. 각 Swing 구성 요소는 사용하는 글꼴과 모양과 느낌에 따라 선호하는 크기가 다릅니다. 따라서 설정된 크기가 있으면 다른 시스템에서 다양한 UI 모양 을 만들 수 있습니다.

  • 때로는 GridBagLayout컨테이너 크기가 원하는 크기보다 작 으면 텍스트 필드에 문제가 발생할 수 있으며 최소 크기가 사용되므로 텍스트 필드가 상당히 줄어들 수 있습니다.

  • JFrame작업을 getMinimumSize()호출 할 때만 재정의를 시행하지 않습니다.setMinimumSize(..)

LayoutManager가 원하는 모든 레이아웃 요구를 정확하게 충족시킬 수 있다고 생각하지 않습니다. 레이아웃의 작은 변형마다 새로운 LayoutManager를 구현해야합니까?

구현하면 예를 사용하는 것을 의미합니다. LayoutManger모든 것을 다룰 수있는 것은 아니며 각각 LayoutManager장단점이 있으므로 최종 레이아웃을 만들기 위해 함께 사용할 수 있습니다.

참고:


3
그 자체로 모순되는 사용자 정의 크기 힌트 제공 : 크기 힌트 (px!) 제공은 구성 요소 의 독점적 인 작업입니다. 자체를 제외한 다른 사람이 알 수없는 (또는 추적 할 수없는) 내부 상태 세부 사항을 기반으로이를 계산합니다. 클라이언트의 관점에서 정의의 수단은 적절한의 LayoutManager 및 / 또는 "의미"크기 관련 속성, 텍스트 구성 요소의 행 / 열 Fi를 수의 측면에서 크기 요구 사항을 구성 할 수있는 구성 요소의 구체화 API를 할 수 있습니다
클레오 파트라

3
@kleopatra 저는 왜 Oracle이 왜 이러한 방법을 사용하는지와 올바른 방법을 알려주는 이유를 알고 싶습니다. 우리는 우리 자신의 선호도를 가지고 있지만 디자이너가 이것을 제안 할 증거가 없을 때 사용하지 말라고 말할 수는 없습니다. 그러나 그것이 현상금을 올리는 이유는 오라클이 이러한 방법을 전혀 사용하지 않는 신뢰할 수있는 출처에서 정보를 제공 할 수있는 다른 사람들을 끌어들이는 이유를 알 수 있습니다 (따라서 setMinimumSize와 같은 경우 나쁜 습관을 가져야 함) 이 분할 창의 오라클 튜토리얼에서 볼 수있는 등 JSplitPane를 같은 것을 촉구했습니다.
데이비드 Kroukamp

4
@David : 문서가 제안 할 때조차도 setXxxSize메소드를 여기에 표시 할 수있는 적기로 보았습니다 . 나는 거의 항상 오버라이드되어야했다 getXxxSize. 여기서 필요한 지오메트리에 접근 할 수있다. 짧은 예제조차도 생각보다 재활용됩니다. 레이아웃 관리자들 사이의 변형을 언급하고 튜토리얼을 인용 한 +1
trashgod

1
D' oh, 위의 의견에서 나는 여기 에 답을 인용하려고했습니다 .
trashgod

13
+1 "아니요, 이러한 메소드를 호출하거나 재정의 할 수 없다는 공식적인 증거는 없습니다." 에 딱 맞다. 답변으로 태그 된 게시물은 일반 BS입니다.
TT.

25

이 여기에 좋은 답변이 많이 있지만 나는 이유에 대한 자세한 조금을 추가 할 당신이 일반적으로 이러한 피해야한다 (질문 단지 중복 항목에 다시 와서) :

몇 가지 예외를 제외하고 이러한 방법을 사용하는 경우 특정 모양과 느낌 (및 시스템 별 설정 (예 : 선호하는 데스크탑 글꼴 등)으로보기에 적합하도록 GUI를 미세 조정할 수 있습니다. 방법 자체는 본질적으로 악한 것이 아니지만 사용하는 일반적인 이유는 다음 과 같습니다 . 레이아웃에서 픽셀 위치 및 크기 조정을 시작하자마자 다른 플랫폼에서 GUI가 깨질 위험이 있습니다 (최소한 나빠 보일 수 있습니다).

이에 대한 예로, 응용 프로그램의 기본 모양과 느낌을 변경해보십시오. 플랫폼에서 사용 가능한 옵션만으로도 결과가 얼마나 나빠질 수 있는지에 놀랄 수 있습니다.

따라서 모든 플랫폼에서 GUI를 기능적이고 멋지게 유지하기 위해 (Java의 주요 이점 중 하나는 플랫폼 간이라는 점을 기억하십시오) 레이아웃 관리자 등에 의존하여 자동으로 크기를 조정해야합니다. 특정 개발 환경 외부에서 올바르게 렌더링되도록 구성 요소

그러나 이러한 방법이 정당화되는 상황을 확실히 생각할 수 있습니다. 다시 말하지만, 그들은 본질적으로 악하지는 않지만 일반적으로 잠재적 GUI 문제를 나타내는 적기입니다. 합병증을 사용하는 경우 합병증이 발생할 가능성이 높은지 항상 확인하고 문제에 대해 다른 모양과 느낌에 독립적 인 해결책이 있는지 항상 시도하고 생각하십시오. 방법이 필요하지 않습니다.

그건 그렇고, 표준 레이아웃 관리자에 좌절감을 느끼면FormLayout 무료로 제공되는 오픈 소스 타사가 많이 있습니다 (예 : JGoodies ' 또는) MigLayout. 일부 GUI 빌더도 내장되어 타사 레이아웃 매니저에 대한 지원 - 이클립스의 WindowBuilder GUI 편집기, 예를 들어,에 대한 지원과 함께 제공 FormLayout하고 MigLayout.


2
+1 사려 깊은 대답-단지 그들이 단순히 다음과 같은 이유로 본질적으로 악하지 않다는 것에 동의하지 않습니다 :-) 일반적으로 외부 고객은 추측 할 수있는 기회가 없으며 외부인이 얻을 수있는 것과 거의 같은 가정이 있습니다. 구성 요소 자체에는 항상 유용한 정보를 반환하는 모든 정보가 있습니다. 그리고 외부인이 방해하는 순간, 그 힌트를 그들이 할 수없는 최신 정보를 유지하는 것은 그들의 책임입니다.
kleopatra

1
글쎄요, 저는 이런 종류의 것들에 대한 "총은 사람을 죽이지 않고 사람들을 죽입니다"라는 더 많은 견해를 가지고 있습니다. :) 경우 누군가가 이러한 방법을 사용, 그들은 필요 (이러한 방법이 적절한 상황이 참으로 드문 이유입니다) 당신이 레이아웃 힌트의 예측할 수없는 사용에 대한 인상 좋은 점 같은 것들을 알고 있어야.
Jason C

선호하는 크기를 설정하는 것이 전혀 큰 깃발이 아니라고 생각합니다. 이 설정되지 않음 입니다 대신 큰 붉은 깃발. 자세히 설명하겠습니다. 아무리 똑똑하더라도 레이아웃 관리자는 GUI 위젯의 논리적 기능에 대해 전혀 모릅니다. 예를 들어, 레이아웃 관리자는 우편 번호를 입력하기위한 JTextField와 이름을 입력하기위한 JTextField를 구별 할 수 없습니다. 마찬가지로 JTextField 옆의 도구 단추 또는 양식 맨 아래의 큰 확인 단추를 구별 할 수 없습니다. 따라서 더 나은 위젯 세트 또는 크기 조정 힌트가 필요합니다.
Gee Bee

@GeeBee Nope, 그것은 실제로 붉은 깃발의 주요 예입니다. 당신이 해야 할 것은 사용하는 것입니다 JTextField.setColumns따라 적절한 사이즈를 조정 열 수를 설정합니다. 그렇게 setPreferredSize하면 크기를 하드 코딩하고 플랫폼 글꼴 크기에 따라 레이아웃이 손상됩니다. 다음은 setColumns적절하게 호출 된 그리드 백 레이아웃의 일부 텍스트 필드입니다 . 버튼의 경우 적절한 레이아웃 / 그리드 가중치를 사용하여 크기를 제어하십시오.
Jason C

@GeeBee 그리고 이제 올바르게 수행 되었으므로 글꼴 크기를 줄이면 텍스트 필드 너비가 어떻게 감소하는지 확인하십시오 : i.snag.gy/ZULulh.jpg . 모든 텍스트 필드 너비를 다시 계산하고 각각에 대해 setPreferredSize를 명시 적으로 다시 호출 해야하는 대신 즉시 글꼴 크기를 변경해도 자동으로 작동합니다. 레이아웃을 무효화하면 크기가 조정됩니다.
Jason C

20

Java Swing에서 레이아웃에 문제가있는 경우 FormLayoutKarsten Lentzsch의 Forms 프리웨어 라이브러리의 일부로 자유롭게 제공 되는 JGoodies를 여기에서 강력하게 추천 할 수 있습니다 .

이 인기있는 레이아웃 관리자는 매우 유연하여 매우 세련된 Java UI를 개발할 수 있습니다.

Karsten의 문서는 여기 에서 찾을 수 있고 Eclipse의 일부 좋은 문서 는 여기 에서 찾을 수 있습니다 .


16

이러한 방법은 대부분의 사람들이 잘 이해하지 못합니다. 이러한 방법을 절대 무시해서는 안됩니다. 이들이 이러한 방법을 존중한다면 레이아웃 관리자에게 달려 있습니다. 이 페이지에는 어떤 레이아웃 관리자가 어떤 방법을 사용하는지 보여주는 표가 있습니다.

http://thebadprogrammer.com/swing-layout-manager-sizing/

8 년 이상 Swing 코드를 작성해 왔으며 JDK에 포함 된 레이아웃 관리자는 항상 내 요구에 부응했습니다. 레이아웃을 달성하기 위해 타사 레이아웃 관리자가 필요하지 않았습니다.

레이아웃 관리자가 필요할 때까지 이러한 방법으로 힌트를 제공해서는 안된다고 말할 것입니다. 크기 조정 힌트를 제공하지 않고 레이아웃을 수행 한 다음 (예 : 레이아웃 관리자가 작업을 수행하도록) 필요한 경우 사소한 수정을 할 수 있습니다.


1
중 약간의 (당신의 부분에) 오해 나 (나의 부분에) 오해, 당신의 선택을 :-) 당신은 (당신의 BoxLayout에서는 관련 대답에, 블로그에, 여기에) 계속 반복 거기에 설정 중요한 인 것으로 XXSize - 실제로 LayoutManager는 XXSize에 관심이 있거나 관심이 없습니다. 즉, 구성 요소에 의한 내부 계산 또는 응용 프로그램 코드에 의해 수동으로 강제 실행되는 방식에 독립적 인 사이징 힌트입니다.
kleopatra

1
나는 당신이 여기에서 무엇을 얻고 있는지 잘 모르겠습니다. 위에서 XXSize () 메서드는 힌트 일뿐입니다. 필요한 경우 레이아웃 관리자에게 약간의 힌트를주는 데 아무런 문제가 없습니다. 내 스윙 코드에서 가끔 setXXSize () 메서드를 찾을 수 있습니다. 많지는 않지만 가끔씩 필요하다는 것을 알았습니다. JComboBox와 JSpinner는 종종 힌트가 필요합니다. 특히 JComboBox는 실현 된 후에 채워집니다. 귀하는 이러한 방법의 모든 사용에 위배되는 것으로 보이며 그 이유를 모르겠습니다. (아마도 나는 이것에 보트를 놓친 사람 일 것입니다).
Michael

5
하지 않는 방법이 힌트이다는 특성이 있습니다 : 구성 요소가 모든 힌트 합리적인 무언가를보고해야 일부 (FI JComboBox가로)하지 않는 - 그래서 maxInteger 또는 반환에. 그것은 버그이며 콤보로 수정해야합니다. 습관에 관해서는 : 유지 보수 동료가 정리해야 할 때 멀리 있어야합니다 :) 하드 코딩 된 힌트는 약간의 변화로 레이아웃을 망가 뜨리는 경향이 있으며 레이아웃이 깨진 이유를 감지하기가 어렵습니다.
kleopatra

15

구성 요소의 자식 (자식 1은 공간의 10 %, 자식 2 40 %, 자식 3 50 %를 사용해야 함) 사이의 비율을 정의 해야하는 상황에서 사용자 정의 레이아웃 관리자를 구현하지 않고도 그것을 달성 할 수 있습니까?

아마 GridBagLayout당신의 요구를 만족시킬 것입니다. 게다가 웹에는 수많은 레이아웃 관리자가 있으며 요구 사항에 맞는 레이아웃 관리자가 있습니다.


답변 해주셔서 감사합니다. "setPreferredSize를 전혀 사용하지 마십시오"라는 의미도 있다고 가정해야합니다.
Heisenbug

1
GridBagLayout은 주어진 컴포넌트에 대해 X와 Y 모두에 "무게"를 지정할 수있는 제약 조건을 사용하므로 LayoutManager는 크기 조정시 여분의 공간으로 수행 할 작업을 결정할 수 있습니다. 그러나 여전히 각 구성 요소 의 기본 크기 를 결정하기 위해 setPreferredSize를 필요로하거나 사용할 수 있습니다. "선호"가 항상 영광을 의미하는 것은 아닙니다. 특별한 경우에는 setMinimumSize 및 setMaximumSize가 필요할 수도 있습니다. 그들은 사악 하지 않습니다, 그것에 사지 마십시오. docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
マ ル ち ゃ ん だ よ

5

나는 그것이 받아 들인 대답과 다른 것을보고 있습니다.

1) 그 방법의 사용을 완전히 피해야합니까?

절대 피하십시오! 레이아웃 관리자에게 컴포넌트의 크기 제약을 표현할 수 있습니다. 레이아웃 관리자를 사용하지 않고 시각적 레이아웃을 직접 관리하려고하면 사용하지 않을 수 있습니다.

불행히도 Swing에는 합리적인 기본 크기가 제공되지 않습니다. 그러나 구성 요소의 크기를 설정하는 대신 합리적인 기본값으로 자체 구성 요소를 내림차순으로 만드는 것이 좋습니다. (이 경우 하위 클래스에서 setXXX를 호출합니다.) 또는 동일한 효과를 위해 getXXX 메소드를 대체 할 수 있습니다.

2) 방법은 이유 때문에 정의되었습니다. 언제 사용해야합니까? 어떤 맥락에서? 어떤 목적으로?

항상. 구성 요소를 작성할 때 해당 구성 요소의 사용에 따라 실제 최소 / 기본 / 최대 크기를 설정하십시오. 예를 들어 영국과 같은 국가 기호를 입력 할 수있는 JTextField가있는 경우 기본 크기는 두 문자 (현재 글꼴 등)에 맞도록 넓어야하지만 더 커질 수는 없습니다. 결국 국가 기호는 두 문자입니다. 반대로, 예를 들어 고객 이름을 입력하기위한 JTextField가있는 경우 20 자에 대한 픽셀 크기와 같은 크기를 선호하지만 레이아웃 크기를 조정하면 더 커질 수 있으므로 최대 크기를 더 많이 설정하십시오. 동시에 0px 너비의 JTextField를 갖는 것은 의미가 없으므로 현실적인 최소 크기를 설정하십시오 (픽셀 크기는 2 자라고 말하십시오).

3) 이러한 방법을 사용하면 어떤 부정적인 결과가 발생합니까?

(화면 해상도가 다른 시스템간에 이식성을 추가하는 것만 생각할 수 있습니다).

부정적인 결과는 없습니다. 레이아웃 관리자를위한 힌트입니다.

4) LayoutManager가 원하는 모든 레이아웃 요구를 정확하게 충족시킬 수 있다고 생각하지 않습니다.

레이아웃의 작은 변형마다 새로운 LayoutManager를 구현해야합니까?

아뇨. 일반적인 접근 방식은 가로 및 세로 레이아웃과 같은 다른 기본 레이아웃 관리자를 계단식으로 배열하는 것입니다.

예를 들어, 아래 레이아웃 :

<pre>
+--------------+--------+
| ###JTABLE### | [Add]  | 
| ...data...   |[Remove]|
| ...data...   |        |
| ...data...   |        |
+--------------+--------+
</pre>

두 부분이 있습니다. 왼쪽과 오른쪽 부분은 가로 레이아웃입니다. 오른쪽 부분은 가로 레이아웃에 추가 된 JPanel이며이 JPanel에는 단추를 세로로 배치하는 세로 레이아웃이 있습니다.

물론 이것은 실제 레이아웃으로 까다로워 질 수 있습니다. 따라서 MigLayout과 같은 그리드 기반 레이아웃 관리자는 심각한 것을 개발하려는 경우 훨씬 좋습니다.

5) 4에 대한 대답이 "예"이면 LayoutManager 클래스가 확산되어 유지 관리가 어려워지지 않습니까?

매우 특별한 것이 필요하지 않으면 레이아웃 관리자를 개발하지 않을 것입니다.

6) 비율을 정의 해야하는 상황에서 ...

구성 요소의 자식 (예 : child1은 공간의 10 %, child2 40 %, child3 50 %를 사용해야 함) 사이에 사용자 정의 LayoutManager를 구현하지 않고도 달성 할 수 있습니까?

기본적으로 원하는 크기를 설정 한 후에는 백분율로 아무것도하지 않을 수 있습니다. 단순히 백분율이 의미가 없기 때문에 (예를 들어 JTextField가 창 크기의 10 %를 갖는 것은 의미가 없습니다.) JTextField가 0px 너비가되도록 창을 축소하거나 JTextField가 다중 디스플레이 설정).

그러나 백분율을 사용하여 GUI의 더 큰 빌딩 블록 (예 : 패널)의 크기를 제어 할 수 있습니다.

JSplitPane을 사용하여 두면의 비율을 미리 설정할 수 있습니다. 또는 MigLayout을 사용하여 백분율, 픽셀 및 기타 단위로 이러한 제약 조건을 설정할 수 있습니다.


정말? 이것은 0이었다? 이것은 100 + 이상으로 받아 들여지는 대답보다 낫습니다. "기본적으로 setPreferredSize를 사용해야합니다!" 끔찍하다. 작업 라인에는 "터치 스크린의 버튼이 [M] x [N] 간격 사이의 [X] x [Y] x]이어야"안전 요구 사항과 같은 특정 크기 요구 사항이 많이 있습니다. btnBar.setPreferredSize( dimTouchBtn );가장 좋은 방법입니다. 사용자 정의 레이아웃 관리자가 필요하지 않습니다. 나는 편리한 경우에 주로 GridBagLayout일부 BorderLayoutBoxLayout중첩을 사용합니다. 이것은 강력한 조합이며 사용하기 쉽습니다.
Loduwijk

위의 의견에 서둘러했습니다. 이것은 내가 받아 들인 대답 후 처음 본 대답이었습니다. 왜 더 이상 투표별로 정렬하지 않습니까? 나는 이것이 원래 투표 수의 핵심 이유 중 하나라고 생각했습니다. 그럼에도 불구하고 나는 여전히 원래의 의견을지지한다. 이것은 더 나은 답변 중 하나입니다. 요점 # 6을 제외하고는별로 좋지 않습니다. 크기를 조정해야하는 이유는 많지만 (소수는 여전히 많을 수 있음) GridBagLayout은 내가 가진 대부분의 경우를 잘 지원합니다.
Loduwijk

나는 크기 조정 대 크기 조정이 종교적 결정으로 취급되지 않을 것이라고 생각합니다. 예를 들어 사전 설정된 고정 해상도로 키오스크 용 GUI를 개발하는 등 아무도 크기를 조정하지 않으려는 경우가 있습니다. 산업용 HMI 디스플레이와 "버튼"의 경우와 같이 다른 목표를 가지고 있다면 터치 스크린의 버튼에 대해 1cm x 1cm 이상 있어야합니다. 이 경우 화면의 DPI는 크기 조정 방법을 설정합니다. 텍스트 필드와 같은 다른 입력은 수직으로 크기가 조정되지 않을 수 있으며 때로는 우편 번호와 같은 수평 크기도 의미가 없습니다.
Gee Bee

0

그 방법의 사용을 완전히 피해야합니까? 나는 그들을 "피해야한다"라고 말하지 않을 것입니다. 당신이 필요하다고 생각한다면, 당신은 아마 뭔가 잘못하고 있다고 말하고 싶습니다. 구성 요소 크기는 상황에 따라 결정됩니다. 예를 들어, 텍스트 구성 요소 크기는 지정한 글꼴과 결합하여 지정한 행과 열 수에 따라 결정됩니다. 단추 및 레이블 크기는 그래픽을 설정 한 경우 그래픽 크기이거나 설정 한 텍스트를 표시하는 데 필요한 공간이됩니다. 각 구성 요소의 크기는 자연스럽고 레이아웃 관리자는 크기를 지정하지 않고도 모든 구성 요소를 배치 할 수 있습니다. 주요 예외는 JScrollPane입니다. JScrollPane에는 크기에 관계없이 크기가 있습니다. 이를 위해 때때로을 호출 setSize()하고 해당 크기가 초기 창 크기를 결정하도록합니다.JFrame.pack(). 일반적으로 창 크기가 JScrollPane 크기를 결정하도록합니다. 사용자는 창의 크기를 결정할 것입니다. 많은 레이아웃 관리자는 어쨌든 설정 한 크기를 무시하므로 많은 일을하지 않습니다.

방법은 이유에 의해 정의되었습니다. 언제 사용해야합니까? 어떤 맥락에서? 어떤 목적으로? 레이아웃 관리자에게 힌트를 제공하기 위해 추가되었다고 생각합니다. 레이아웃 관리자가 새롭고 사람들이 완전히 신뢰하지 않았기 때문에 역사적인 이유로 작성되었을 수 있습니다. 나는 새로운 패러다임을 배우고 싶지 않기 때문에 레이아웃 관리자를 피하고 모든 것을 수동으로 배치 한 소수의 개발자를 알고 있습니다. 끔찍한 생각입니다.

이러한 방법을 사용하면 어떤 부정적인 결과가 발생합니까? (화면 해상도가 다른 시스템간에 이식성을 추가하는 것만 생각할 수 있습니다). 그것들은 효과가 없으며, 객체가 압착되지 않거나 자연스럽지 않은 크기로 늘어나면서 잘못된 레이아웃을 생성합니다. 그리고 레이아웃이 부서지기 쉽습니다. 창 크기를 변경하면 레이아웃이 깨져서 잘못된 위치에 배치되는 경우가 있습니다.

LayoutManager가 원하는 모든 레이아웃 요구를 정확하게 충족시킬 수 있다고 생각하지 않습니다. 레이아웃의 작은 변형마다 새로운 LayoutManager를 구현해야합니까? 새로운 LayoutManager를 "구현"해서는 안됩니다. 기존 인스턴스를 인스턴스화해야합니다. 하나의 창에서 여러 레이아웃 관리자를 자주 사용합니다. 각 JPanel에는 자체 레이아웃 관리자가 있습니다. 일부 사람들은 유지 관리가 어렵 기 때문에 중첩 된 레이아웃을 사용합니다. 내가 그것을 사용할 때, 나는 각자가 무엇을하는지 더 쉽게 볼 수 있도록 각각의 고유 한 생성 방법을 제공합니다. 그러나 나는 결코 레이아웃 관리자를 "구현"하지 않습니다. 나는 단지 그들을 인스턴스화합니다.

4에 대한 대답이 "예"이면 LayoutManager 클래스가 확산되어 유지 관리가 어려워지지 않습니까? 레이아웃의 약간의 변형을 위해 새로운 레이아웃 관리자 클래스를 구현하는 경우 잘못 사용하고 있습니다. 새로운 레이아웃 관리자를 구현하는 경우 무언가 잘못되었을 수 있습니다. LayoutManager 클래스를 확장 한 유일한 시점은 확대 / 축소 슬라이더를 JScrollPane에 추가하는 것이 었습니다.

Component의 자식들 사이에 비율을 정의해야하는 상황에서 (예를 들어, child1은 공간의 10 %, child2 40 %, child3 50 %를 사용해야 함), 사용자 정의 LayoutManager를 구현하지 않고도 달성 할 수 있습니까? JSplitPane에는 각 구성 요소의 백분율을 지정하는 방법이 있습니다. 디바이더는 기본적으로 움직일 수 있지만 원하는 경우 끌 수 있습니다. 나는 그 기능을 많이 사용하지 않습니다. 일반적으로 설정된 크기를 차지하는 일부 구성 요소가 있으며 나머지 공간은 스크롤 창에 의해 차지됩니다. 스크롤 창 크기는 창 크기에 따라 조정됩니다. 두 개의 스크롤 창이 나란히 있으면 JSplitPane에 배치하고 사용자가 창을 확장 및 축소 할 때 각각에 주어진 새 공간의 백분율을 지정할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.