Чи слід уникати використання встановлених (бажаних | максимальних | мінімальних) методів розміру в Java Swing?


481

Мене кілька разів критикували за те, що я запропонував використовувати наступні методи:

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

на Swingкомпоненти. Я не бачу альтернативи їх використанню, коли хочу визначити пропорції між відображеними компонентами. Мені сказали це:

Відповідно до макетів, відповідь завжди однакова: використовуйте відповідний LayoutManager

Я трохи шукав в Інтернеті, але не знайшов всебічного аналізу цього питання. Тому у мене є такі питання:

  1. Чи варто повністю уникати використання цих методів?
  2. Методи були визначені причиною. То коли я повинен їх використовувати? У якому контексті? Для яких цілей?
  3. Які саме негативні наслідки використання цих методів? (Я можу подумати лише про те, щоб додати портативність між системами з різною роздільною здатністю екрана).
  4. Я не думаю, що будь-який LayoutManager може точно задовольнити всі бажані потреби в компонуванні. Чи дійсно мені потрібно впроваджувати новий LayoutManager для кожної невеликої зміни в моєму макеті?
  5. Якщо відповідь на 4 - "так", чи не призведе це до поширення класів LayoutManager, які стане важко підтримувати?
  6. У ситуації, коли мені потрібно визначити пропорції між дітьми компонента (наприклад, child1 повинен використовувати 10% простору, child2 40%, child3 50%), чи можна цього досягти, не застосовуючи користувальницький LayoutManager?

Відповіді:


236
  1. Чи варто повністю уникати використання цих методів?

    Так для коду програми.

  2. Методи були визначені причиною. То коли я повинен їх використовувати? У якому контексті? Для яких цілей?

    Я не знаю, особисто я вважаю це випадковою ситуацією в дизайні API. Трохи змушені складеними компонентами, що мають спеціальні уявлення про розміри дітей. "Трохи", тому що вони повинні були реалізувати свої потреби за допомогою спеціального LayoutManager.

  3. Які саме негативні наслідки використання цих методів? (Я можу подумати лише про те, щоб додати портативність між системами з різною роздільною здатністю екрана.)

    Деякі (неповні, і, на жаль, посилання порушені через міграцію SwingLabs на java.net), технічні причини, наприклад, згадуються в Правилах (hehe) або у посиланні @bendicott, знайденому в його коментарі до моєї відповіді . У соціальному плані, виставляючи тонни роботи своєму нещасному товаришеві, який повинен підтримувати код і повинен відшукати зламану схему.

  4. Я не думаю, що будь-який LayoutManager може точно задовольнити всі бажані потреби в компонуванні. Чи дійсно мені потрібно впроваджувати новий LayoutManager для кожної невеликої зміни в моєму макеті?

    Так, є LayoutManagers досить потужні, щоб задовольнити дуже гарне наближення до "всіх потреб у компонуванні". Велика трійка - це JGoodies FormLayout, MigLayout, DesignGridLayout. Тому ні, на практиці ви рідко пишете програми LayoutManagers за винятком простих вузькоспеціалізованих середовищ.

  5. Якщо відповідь на 4 - "так", чи не призведе це до поширення класів LayoutManager, які стане важко підтримувати?

    (Відповідь на 4 - "ні".)

  6. У ситуації, коли мені потрібно визначити пропорції між дітьми компонента (наприклад, дитина 1 повинна використовувати 10% місця, дитина 2 40%, дитина 3 50%), чи можна цього досягти, не застосовуючи користувальницький LayoutManager?

    Будь-який з Big-Three може навіть не може GridBag (ніколи не заважав по-справжньому опанувати, занадто багато проблем за занадто мало енергії).


4
Я не зовсім впевнений, що згоден з цією порадою принаймні у двох ситуаціях. 1) Користувальницькі компоненти, що надаються 2) Використання JEditorPaneHTML-коду, який сам по собі не пропонує ширини. ОТО я не впевнений, чи щось я пропустив. Я ретельно перегляну відповіді на тему, але мені було цікаво, чи є у вас коментарі, особливо щодо останнього випадку.
Ендрю Томпсон

2
@Andrew Thompson 1) нестандартні компи: саме комп, який відповідає за повернення корисних підказів щодо компонування, якщо вони не мають імпульсу, баггі 2) навіть основні компроміси баггі ;-) 3) Я не маю уваги пробіл (хоча це не було Навмисно цього разу, дякую :-)
kleopatra

8
Я не можу повірити, що прийнята відповідь - це відповідь, щоб уникнути використання методів setXXX (). Іноді їх просто потрібно, щоб надати підказку менеджеру компонування. Якщо ви викладаєте панель, тоді вам слід абсолютно сміливо використовувати ці методи, коли це необхідно. Говорячи, що я думаю, якщо ви скористаєтесь відповідним менеджером компонування, ви виявите, що ці методи не потребують дуже часто, але іноді вони вам просто потрібні. Спробуйте помістити JComboBox або JSpinner в X_AXIS BoxLayout і не користуватися ними, вважайте, що там знайдете потрібний setMaximumSize ().
Майкл

5
@Michael ні, мені це абсолютно не потрібно - відповідь завжди використовувати пристойний LayoutManager і робити будь-які тонкі налаштування на рівні менеджера (проти рівня компонентів)
kleopatra

5
Ви постійно говорите: "використовуйте пристойний LayoutManager і повідомляйте, яких розмірів ви хочете" по всьому stackoverflow, але ви ніколи не наводите конкретних прикладів "пристойного" 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-) кадр з розміром aa specifc відносно бажаного ... розмір кадру, а не вміст
kleopatra

2
@kleopatra: просто щоб бути трохи наполегливим: якщо методи setXXSize ніколи не повинні використовуватися ззовні, чому їх не оголосили приватними чи захищеними? Це не брак дизайну? Чи загальнодоступний модифікатор неявно не каже користувачеві, що може використовувати ці методи?
Heisenbug

2
Я маю згоду з @kleopatra: setPreferredSize()завжди замінює обчислення компонента довільним вибором.
trashgod

1
@trashgod +100 для вас. Я думаю, що немає проблем з перекриттям цих методів, навіть викликом їх (але, звичайно, це означатиме, що у вас є власний компонент, таким чином,
переосмислення

5
@DavidKroukamp: Дякую Я відкладаю кращий досвід клеопатри, але бачу цінність у критичному дослідженні протилежної точки зору.
trashgod

47

Чи варто повністю уникати використання цих методів?

Ні, немає офіційних доказів, які б дозволяли викликати або переосмислювати ці методи, не дозволяється. Насправді Oracle каже, що ці методи використовуються для надання підказки щодо розміру: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .

Вони також можуть бути відмінені (що є найкращою практикою для Swing) під час розширення компонента Swing (замість виклику методу у спеціальному екземплярі компонента)

Найголовніше, незалежно від того, як ви визначаєте розмір свого компонента, будьте впевнені, що контейнер вашого компонента використовує диспетчер макетів, який дотримується потрібного розміру компонента.

Методи були визначені причиною. То коли я повинен їх використовувати? У якому контексті? Для яких цілей?

Коли вам потрібно надати спеціальні підказки щодо розміру диспетчеру макетів контейнерів, щоб компонент був добре викладений

Які саме негативні наслідки використання цих методів? (Я можу лише подумати, щоб додати портативність між системами з різною роздільною здатністю екрана).

  • Багато менеджерів компонування не звертають уваги на запитуваний максимальний розмір компонента. Однак BoxLayoutі SpringLayoutробити. Крім того, GroupLayoutнадається можливість чітко встановити мінімальний, бажаний або максимальний розмір, не торкаючись компонента.

  • Переконайтеся, що вам дійсно потрібно встановити точний розмір компонента. Кожен компонент Swing має різний бажаний розмір, залежно від використовуваного шрифту та зовнішнього вигляду. Таким чином, розмір заданого розміру може створювати різноманітний зовнішній вигляд інтерфейсу користувача в різних системах

  • іноді можуть виникати проблеми GridBagLayoutі з текстовими полями, коли, якщо розмір контейнера менший за бажаний розмір, мінімальний розмір звикає, що може спричинити скорочення текстових полів досить сильно.

  • JFrameне примушує переосмислювати getMinimumSize()лише заклики setMinimumSize(..)до своїх творів

Я не думаю, що будь-який LayoutManager може точно задовольнити всі бажані потреби в компонуванні. Чи дійсно мені потрібно впроваджувати новий LayoutManager для кожної невеликої зміни в моєму макеті?

Якщо, маючи на увазі, ви маєте на увазі використання, то так. Не LayoutMangerможна впоратися з усім, кожен LayoutManagerмає свої плюси і мінуси, тому кожен може бути використаний разом для отримання остаточного плану.

Довідка:


3
надати підказки щодо настроюваних розмірів, що саме по собі суперечить: надання підказки про розмір (у px!) є ексклюзивним завданням компонента. Він розраховує їх на основі внутрішніх деталей стану, які жодна інша сторона, окрім самої себе, не може знати (і не може відслідковувати). З точки зору клієнта, засобами налаштування можуть бути відповідний LayoutManager та / або спеціалізувати api на компоненті, що дозволяє налаштувати вимоги до розміру з точки зору "семантичних" властивостей, що відповідають розміру, fi кількості рядків / стовпців у текстовому компоненті
kleopatra

3
@kleopatra Я все ще хотів би знати, чому Oracle потім розповідає нам, як використовувати ці методи та правильний спосіб їх використання. У нас можуть бути власні переваги, але ми не можемо сказати, що дизайнери вважають, що його не слід використовувати, коли немає ніяких доказів, які б це підтверджували. Але тому я виставив щедрості бачити, можливо, якщо б це залучало інших, які могли б дати інформацію з достовірного джерела, де Oracle заявляє, що ці методи взагалі не використовують (таким чином, це погана практика, якщо ви це робите, наприклад, setMinimumSize повинен бути закликають такі речі, як JSplitPane тощо. Це можна побачити в підручнику Oracle розділених панелей.
Девід Крукамп

4
@David: Я прийшов розглядати setXxxSizeметоди як червоний прапор, який я можу закінчити тут , навіть коли документи пропонують це. Я майже завжди повинен був перекрити getXxxSize, де можна отримати доступ до необхідної геометрії; і навіть короткі приклади переробляють більше, ніж я хочу подумати. +1 для згадування варіантів серед менеджерів макетів та цитування підручника.
trashgod

1
До'о, у своєму коментарі вище, я мав на увазі відповісти тут .
trashgod

13
+1 "Ні, немає жодних офіційних доказів, які б дозволяли викликати або змінювати ці методи, заборонено." Пляма на. Повідомлення, позначене як відповідь, є простим BS.
ТТ.

25

Тут є багато хороших відповідей, але я хочу додати трохи більше про причини, чому вам слід зазвичай уникати цих питань (питання просто з'явилося знову в двох примірниках теми):

За кількома винятками, якщо ви використовуєте ці методи, ви, ймовірно, добре налаштовуєте свій графічний інтерфейс, щоб він добре виглядав під конкретний зовнішній вигляд (і з налаштуваннями для вашої системи, наприклад, бажаним шрифтом на робочому столі тощо). Самі методи самі по собі не є злими, але типовими причинами їх використання є . Як тільки ви почнете налаштування піксельних позицій та розмірів у макеті, ви ризикуєте зламати графічний інтерфейс (або, як мінімум, погано виглядати) на інших платформах.

Як приклад цього, спробуйте змінити зовнішній вигляд програми за замовчуванням. Навіть тільки з наявними на вашій платформі опціями ви можете здивуватися тому, наскільки погано можна отримати результати.

Отже, для збереження вашого графічного інтерфейсу функціональним та чудовим на всіх платформах (пам’ятайте, однією з головних переваг Java є її крос-платформа), вам слід покластися на менеджерів макетів тощо, щоб автоматично регулювати розміри ваші компоненти, щоб він відображався правильно поза вашим конкретним середовищем розробки.

Все, що сказано, ви безсумнівно можете уявити ситуації, коли ці методи виправдані. Знову ж таки, вони по суті не злі, але їх використання зазвичай є великим червоним прапором, що вказує на можливі проблеми з графічним інтерфейсом. Просто переконайтеся, що ви знаєте про високий потенціал ускладнень, якщо / коли ви їх використовуєте, і завжди намагайтеся подумати, чи є інше незалежне від виду і відчуття рішення для ваших проблем - частіше за все ви виявите, що ці методи не потрібні.

До речі, якщо ви зриваєтесь із стандартними менеджерами макетів, є багато хороших безкоштовних, відкритих джерел сторонніх розробників, наприклад JGoodies 'FormLayout , або MigLayout. Деякі будівельники графічного інтерфейсу навіть мають вбудовану підтримку сторонніх менеджерів макетів - редактора графічного інтерфейсу Eclipse WindowBuilder, наприклад, поставляються із підтримкою для FormLayoutта MigLayout.


2
+1 уважна відповідь - просто не погоджуйтеся з тим, що вони по суті не є злі, просто тому, що вони :-) Зазвичай зовнішні клієнти не мають жодного шансу здогадатися - а прості припущення є такими ж близькими, як можуть отримати сторонні люди - на півдорозі правильні підказки: лише в самих компонентах завжди є вся інформація, щоб повернути що-небудь корисне. І з того моменту, як сторонні люди перешкоджають, їхня відповідальність є актуальні ті підказки, які вони не можуть.
Клеопатра

1
Ну, ви знаєте, я маю на увазі більше "гармати не вбивають людей, люди вбивають людей". :) Якщо хтось використовує ці методи, він повинен усвідомлювати такі речі, як добрі моменти, які ви наближаєте щодо непередбачуваного використання натяків на компонування (саме тому ситуації, коли ці методи доречні, дійсно рідкісні).
Джейсон C

Я думаю, що встановлення бажаного розміру зовсім не є великим червоним прапором. Чи не встановлюючи це є великим червоним прапором замість цього. Дозвольте мені детальніше. Менеджер компонування - як би він не був розумним - не має поняття про логічну функцію віджета gui. Наприклад, менеджер макета не може розрізняти JTextField для введення поштового індексу та JTextField для введення імені. Аналогічно, він не може розрізнити кнопку інструменту поруч із JTextField або велику кнопку OK у нижній частині форми. Тому потрібен або кращий набір віджетів, або деякі підказки щодо розмірів, ні?
Gee Bee

@GeeBee Nope, це насправді прекрасний приклад червоного прапора. Що ви повинні зробити, це використовувати JTextField.setColumnsдля встановлення кількості стовпців, який відповідно регулює бажаний розмір. Якщо ви це зробите, setPreferredSizeто вам важко кодувати розмір, який порушить ваш макет залежно від розміру шрифту платформи. Ось декілька текстових полів у макеті мішок з сіткою із setColumnsвідповідним викликом . Для ваших кнопок використовуйте відповідні макети / ваги сітки для контролю розмірів.
Джейсон C

@GeeBee І тепер, зробивши це правильно, помітьте, як зменшуються ширини текстових полів, коли я зменшую розмір шрифту: i.snag.gy/ZULulh.jpg . Навіть змінюючи розмір шрифту на льоту, зараз працює автоматично, а не вам, скажімо, доведеться перерахувати всі ширини текстових полів і явно зателефонувати setPreferredSize для кожної, все, що вам потрібно зробити, - це визнати недійсним макет, і їх розміри будуть коригуватися.
Джейсон C

20

Якщо у вас виникли проблеми з макетами Java Swing, я настійно рекомендую JGoodies, що FormLayoutнадається безкоштовно у рамках безкоштовної бібліотеки Forms від Карстен Ленцш тут .

Цей дуже популярний менеджер макетів надзвичайно гнучкий, що дозволяє розробляти дуже відполіровані інтерфейси Java.

Ви знайдете тут документацію Карстен , а також досить непогану документацію від затемнення тут .


16

Ці методи погано розуміються більшістю людей. Вам абсолютно не слід ігнорувати ці методи. Це, якщо вони шанують ці методи, залежить від менеджера макетів. На цій сторінці є таблиця, яка показує, які менеджери макетів шанують, який із цих методів:

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

Я пишу код Swing 8+ років, і менеджери макетів, включені до JDK, завжди задовольняли мої потреби. Мені ніколи не потрібен сторонній менеджер макетів, щоб досягти своїх макетів.

Я скажу, що вам не слід намагатися давати підказки менеджеру компонування з цими методами, поки ви не впевнені, що вони вам потрібні. Робіть свою компоновку, не даючи жодних підказок щодо розмірів (тобто нехай менеджер макета виконує свою роботу), і тоді ви можете внести незначні виправлення, якщо вам потрібно.


1
або є незначне неправильне уявлення (з вашого боку) або непорозуміння (з мого боку), прийміть свій вибір :-) Ви постійно повторюєте (тут, у своєму блозі, у своїй відповіді, що стосується BoxLayout), набір XXSize є важливим - власне LayoutManager зацікавлений у XXSize, тобто підказці про розмір незалежно від того, як це відбулося (внутрішній розрахунок за компонентом або вручну вимушений кодом програми)
kleopatra

1
Я не впевнений, що розумію, що ви тут отримуєте. Я вже згадую, що методи XXSize () - лише підказки. Я дійсно не бачу нічого поганого в тому, щоб дати менеджеру макета трохи підказки, якщо це потрібно. У моєму коді swing ви знайдете випадковий метод setXXSize (). Не багато, але раз у раз я вважаю, що вони потрібні. JComboBox та JSpinner часто потребують підказки. Особливо JComboBox, який заповнюється після його реалізації. Ви, здається, проти будь-якого використання цих методів, і я не знаю чому. (можливо, я є тим, хто пропускає човен на цьому, я здогадуюсь).
Майкл

5
не методи - це підказки, властивості такі: компоненти повинні повідомляти про щось підходяще для всіх підказок, деякі (як, наприклад, JComboBox) - не повертаючи maxInteger або близько того. Це помилка, і її слід виправити комбо. Що стосується вашої звички: не забудьте бути далеко, коли колег, що обслуговує, повинен це прибрати :) Наполегливі підказки, як правило, руйнують макет при найменших змінах, і їх важко визначити причиною зламаного плану.
Клеопатра

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 не має розумних розмірів за замовчуванням. Однак замість того, щоб встановлювати розміри компонента, краще OOP спустити власний компонент з розумними значеннями за замовчуванням. (У такому випадку ви викликаєте setXXX у своєму нащадковому класі.) Або ви можете замінити методи getXXX для того ж ефекту.

2) Методи були визначені причиною. То коли я повинен їх використовувати? У якому контексті? Для яких цілей?

Завжди. Коли ви створюєте компонент, встановіть його реалістичний мінімальний / бажаний / максимальний розмір відповідно до використання цього компонента. Наприклад, якщо у вас є JTextField для введення символів країни, таких як Великобританія, його бажаний розмір повинен бути настільки широким, щоб відповідати двом символам (з поточним шрифтом тощо), але, напевно, безглуздо дозволяти йому зростати більше. Адже символи країни - це дві символи. Навпаки, якщо у вас є JTextField для введення, наприклад, імені клієнта, він може мати бажаний розмір на зразок розміру пікселя на 20 символів, але може зрости до більшого, якщо розмір буде змінено, тому встановіть максимальний розмір більше. У той же час, мати JTextField з 0 пікселями в ширину безглуздо, тому встановіть реалістичний мінімальний розмір (я б сказав, розмір пікселя - 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 стає шириною 0 пікселів або може розширити вікно так, що JTextField знаходиться на двох дисплеях на налаштування декількох дисплеїв).

Але, можливо, ви можете використовувати відсотки, щоб контролювати розміри великих будівельних блоків вашого gui (панелі, наприклад).

Ви можете використовувати JSplitPane, де ви можете попередньо встановити співвідношення двох сторін. Або ви можете використовувати MigLayout, який дозволяє встановлювати такі обмеження у відсотках, пікселях та інших одиницях.


Дійсно? Це було при 0? Це краще, ніж прийнята відповідь, що має більше 100 підйомів. Це, в основному, говорить: "Ти повинен використовувати setPreferredSize!" що ТЕРМІНОВО. У моїй роботі є багато специфічних вимог до розміру, наприклад, "Кнопки на сенсорних екранах повинні бути [X] по [Y] з [M] x [N] проміжком між" вимогою безпеки. btnBar.setPreferredSize( dimTouchBtn );це найкращий спосіб зробити це. Безпосередньо, немає необхідності у користувальницькому менеджері компонування. Я в основному користуюся GridBagLayoutз деякими BorderLayoutі BoxLayout, гніздячись, коли зручно. Це сильне поєднання і просте у використанні.
Loduwijk

Я був поспішний у своєму вище коментарі. Це була перша відповідь, яку я побачив після прийнятої відповіді. Чому ТАК більше не сортується за підрахунком голосів? Я подумав, що це була одна з основних причин підрахунку голосів спочатку. Я все ще залишаюся оригінальним коментарем; це одна з кращих відповідей. За винятком пункту №6 - той не такий великий. Причин для зміни розміру є безліч (меншість все ще може бути великою кількістю), і GridBagLayout підтримує це добре в більшості випадків, з якими я мав місце.
Loduwijk

Я думаю, що розмір проти не зміна не повинен піддаватися релігійному рішенню. Існують випадки використання, коли ніхто ніколи не хоче нічого змінювати розмір, наприклад, якщо ви розробляєте GUI для кіоску, заздалегідь встановленою фіксованою роздільною здатністю. Якщо у вас є різні цілі, такі як промислові дисплеї HMI та корпус "кнопок", то так, вам потрібно мати принаймні 1 см на 1 см для кнопки на сенсорному екрані. У цьому випадку DPI екрана встановлює спосіб зміни розміру. Інші введення, такі як текстові поля, можуть взагалі не змінювати вертикально, а іноді (наприклад, поштовий індекс) горизонтальний розмір також є безглуздим.
Gee Bee

0

Чи варто повністю уникати використання цих методів? Я б не сказав "уникати" їх. Я б сказав, що якщо ви думаєте, що вони вам потрібні, ви, ймовірно, робите щось не так. Розміри компонентів визначаються в контексті. Наприклад, розміри текстових компонентів визначаються кількістю вказаних вами рядків та стовпців у поєднанні з обраним вами шрифтом. Ваш розмір кнопки та мітки буде розміром графіки, якщо ви встановите її, або простором, необхідним для відображення заданого вами тексту. Кожен компонент має натуральний розмір, і менеджери макетів використовуватимуть їх, щоб викласти все, не вказуючи розміри. Основний виняток - JScrollPane, який має розмір, незалежний від того, що він містить. Для тих, кого я іноді дзвоню setSize(), і нехай цей розмір визначає початковий розмір вікна, зателефонувавшиJFrame.pack(). Зазвичай я дозволяю розміру вікна визначати розмір JScrollPane. Користувач визначить розмір вікна. Багато менеджерів компонування ігнорують встановлені вами розміри, тому вони часто не приносять користі.

Методи були визначені причиною. То коли я повинен їх використовувати? У якому контексті? Для яких цілей? Я вважаю, що їх додали, щоб надати підказки менеджерам макетів. Вони, можливо, були написані з історичних причин, тому що менеджери верстки були новими, і люди не повністю їм довіряли. Я знаю кількох розробників, які уникали менеджерів макетів і розміщували все вручну, просто тому, що вони не хотіли заважати вивченню нової парадигми. Це жахлива ідея.

Які саме негативні наслідки використання цих методів? (Я можу подумати лише про те, щоб додати портативність між системами з різною роздільною здатністю екрана). Вони неефективні, і вони створюють погані розкладки, коли предмети стискаються або розтягуються до неприродних розмірів. І макети будуть крихкими. Зміни розміру вікна іноді порушують макет і помістять речі в неправильні місця.

Я не думаю, що будь-який LayoutManager може точно задовольнити всі бажані потреби в компонуванні. Чи дійсно мені потрібно впроваджувати новий LayoutManager для кожної невеликої зміни в моєму макеті? Ви не повинні "впроваджувати" новий LayoutManager. Вам слід інстанціювати існуючі. Я часто використовую кілька менеджерів макетів в одному вікні. У кожного JPanel буде власний менеджер макетів. Деякі люди балакають за вкладеними макетами, оскільки їх важко підтримувати. Коли я їх використовую, я даю кожному своєму способу створення, щоб було легше бачити, що кожен робить. Але я ніколи не «реалізую» менеджера макетів. Я просто інстанціюю їх.

Якщо відповідь на 4 - "так", чи не призведе це до поширення класів LayoutManager, які стане важко підтримувати? Якщо ви впроваджуєте нові класи диспетчера макетів для невеликих варіацій у компонуванні, ви використовуєте їх неправильно. Якщо ви просто впроваджуєте нові менеджери верстки, ви, ймовірно, робите щось не так. Єдиний раз, коли я розширив клас LayoutManager, це було додати повзунок масштабування до JScrollPane.

У ситуації, коли мені потрібно визначити пропорції між дітьми компонента (наприклад, child1 повинен використовувати 10% простору, child2 40%, child3 50%), чи можна цього досягти, не застосовуючи користувальницький LayoutManager? У JSplitPane є спосіб вказати відсоток, який повинен отримувати кожен компонент. Дільник розділений за замовчуванням, але ви можете вимкнути його, якщо хочете. Я мало використовую цю функцію. У мене зазвичай є деякі компоненти, які займають заданий розмір, а решту місця займає панель прокрутки. Розмір панелі прокрутки буде регулюватися залежно від розміру вікна. Якщо у вас є дві області прокрутки поруч, ви можете помістити їх у JSplitPane і вказати відсоток нового простору, що надається кожному, коли користувач розширює і стискає вікна.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.