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

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

  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를 구현하지 않고도 달성 할 수 있습니까?


답변

  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조차도 할 수 없습니다.


답변

몇 가지 휴리스틱 :

  • 여기 에 표시된대로 고유 한 구성 요소를 만들 때와 같이 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());
            }
        }
    }
}


답변

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

아니요, 이러한 메서드를 호출하거나 재정의하는 것이 허용되지 않는다는 공식적인 증거는 없습니다. 실제로 오라클은 이러한 방법이 크기 힌트를 제공하는 데 사용된다고 말합니다 ( 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장단점이 있으므로 최종 레이아웃을 만들기 위해 함께 사용할 수 있습니다.

참고:


답변

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

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

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

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

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

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


답변

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

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

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


답변

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

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

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

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


답변

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

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