Следует ли мне избегать использования методов set (Preferred | Maximum | Minimum) Size в 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), технические причины, например, упомянуты в Правилах (хе-хе) или в ссылке @bendicott, найденной в его / ее комментарии к моему ответу . В социальном плане выкладываете кучу работы на вашего несчастного товарища, который должен поддерживать код и выискивать сломанный макет.

  4. Я не думаю, что любой LayoutManager может точно удовлетворить все желаемые потребности макета. Действительно ли мне нужно реализовывать новый LayoutManager для каждого небольшого изменения моего макета?

    Да, есть LayoutManager, достаточно мощный, чтобы удовлетворить очень хорошее приближение ко всем потребностям макета. Большая тройка - это JGoodies FormLayout, MigLayout, DesignGridLayout. Так что нет, на практике вы редко пишете LayoutManager, за исключением простых узкоспециализированных сред.

  5. Если ответ на 4 «да», не приведет ли это к увеличению числа классов LayoutManager, которые будет трудно поддерживать?

    (Ответ на 4 «нет».)

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

    Любой из Большой тройки может, даже не может GridBag (никогда не удосужился по-настоящему освоить, слишком много проблем для слишком маленькой власти).

Kleopatra
источник
4
Я не совсем уверен, что согласен с этим советом по крайней мере в двух ситуациях. 1) Пользовательские компоненты рендеринга 2) Использование JEditorPaneс HTML, который сам по себе не предлагает ширину. ОТО Я не уверен, что я что-то пропустил. Я внимательно рассмотрю ответы в ветке, но мне было интересно, есть ли у вас какие-либо комментарии, особенно по поводу последнего случая.
Эндрю Томпсон
2
@ Andrew Thompson 1) пользовательские компы: сам комп отвечает за возврат полезных подсказок макета, если они не содержат ошибок 2) даже основные компы глючат ;-) 3) Я не возражаю против пробелов (хотя это не было намеренно, на этот раз, спасибо :-)
kleopatra
8
Я не могу поверить, что принятым ответом является то, что следует избегать использования методов setXXX (). Иногда они просто необходимы, чтобы предоставить подсказку менеджеру макета. Если вы кладете панель, то вы должны абсолютно свободно использовать эти методы при необходимости. Сказав это, я думаю, что если вы воспользуетесь соответствующим менеджером компоновки, вы обнаружите, что вам не нужны эти методы очень часто, но иногда вы просто нуждаетесь в них. Попробуйте поместить JComboBox или JSpinner в X_AXIS BoxLayout и не использовать их, поверьте, вы обнаружите, что там вам нужно установить setMaximumSize ().
Майкл
5
@ Михаил, нет, мне это абсолютно не нужно - ответ всегда заключается в том, чтобы использовать достойный LayoutManager и делать любые тонкие настройки на уровне менеджера (по сравнению с уровнем компонентов)
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());
            }
        }
    }
}
trashgod
источник
2
не согласен (как вы могли догадаться :-) с аргументами «внешних факторов»: свойства XXSize предназначены для выражения только внутренних потребностей. Тонкая настройка извне - это хакерство. Если вы хотите (Внутренний или J-) кадр с определенным размером относительно его предпочтительного размера ... размер кадра, а не содержимого
kleopatra
2
@kleopatra: просто чтобы быть немного настойчивым: если методы setXXSize никогда не должны использоваться извне, почему они не были объявлены частными или защищенными? Разве это не недостаток дизайна? Разве публичный модификатор неявно говорит пользователю, который может использовать эти методы?
Heisenbug
2
Я должен согласиться с @kleopatra: setPreferredSize()всегда заменяет вычисление компонента произвольным выбором.
trashgod
1
@trashgod +100 к вам Я думаю, что нет проблем с переопределением этих методов, даже вызовом их (но, конечно, это будет означать, что у вас есть пользовательский компонент, поэтому переопределение будет лучше)
David Kroukamp
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
предоставляйте индивидуальные подсказки по размеру, что само по себе является противоречием: предоставление подсказок по размеру (в пикселях!) является исключительной задачей компонента. Он рассчитывает их на основе внутренних сведений о состоянии, которые не может знать ни одна из сторон, кроме себя (и не может отслеживать). С точки зрения клиента, средством настройки может быть подходящий LayoutManager и / или специализированный API для компонента, который позволяет настраивать требования к размеру в терминах «семантических» свойств, соответствующих размеру, например, числа строк / столбцов в текстовом компоненте
kleopatra
3
@kleopatra Я все еще хотел бы знать, почему Oracle тогда говорит нам, как использовать эти методы и как их правильно использовать. У нас могут быть свои собственные предпочтения, но мы не можем сказать, что дизайнеры считают, что их нельзя использовать, когда нет никаких доказательств этого. Но именно поэтому я выставил награду, возможно, она привлечет других, которые могли бы предоставить информацию из заслуживающего доверия источника, где оракул заявляет, что вообще не использует эти методы (таким образом, делая это плохой практикой, например, setMinimumSize должен быть вызывал такие вещи, как JSplitPane и т. д. Это можно увидеть в учебнике Oracle по разделенным панелям
Дэвид Крукамп,
4
@ Дэвид: Я пришел, чтобы увидеть setXxxSizeметоды как красный флаг, который я могу поставить здесь , даже когда это предложат документы. Я почти всегда должен был переопределить getXxxSize, где каждый имеет доступ к необходимой геометрии; и даже короткие примеры перерабатываются больше, чем я хочу думать. +1 за упоминание вариаций среди менеджеров по макету и цитирование учебника.
trashgod
1
О, в моем комментарии выше я хотел привести здесь ответ .
trashgod
13
+1 «Нет, нет никаких официальных доказательств того, что использование или переопределение этих методов запрещено». Пятно на. Пост, отмеченный как ответ, является простым BS.
ТТ.
25

Здесь есть много хороших ответов, но я хочу добавить немного больше о причинах, по которым вам следует избегать их (вопрос только что снова возник в дублирующей теме):

За некоторыми исключениями, если вы используете эти методы, вы, вероятно, настраиваете свой графический интерфейс, чтобы он хорошо выглядел под конкретный внешний вид (и с вашими системными настройками, например, предпочитаемым шрифтом рабочего стола и т. Д.). Сами методы не являются по своей природе зол, но типичные причины для их использования являются . Как только вы начинаете настраивать положения и размеры пикселей в макете, вы рискуете сломать графический интерфейс (или, как минимум, выглядеть плохо) на других платформах.

Как пример этого, попробуйте изменить внешний вид вашего приложения по умолчанию. Даже с опциями, доступными на вашей платформе, вы можете быть удивлены тем, насколько плохо могут быть получены результаты.

Таким образом, во имя поддержания функциональности и привлекательности графического интерфейса пользователя на всех платформах (помните, одним из основных преимуществ Java является его кроссплатформенность), вам следует полагаться на менеджеры компоновки и т. Д., Чтобы автоматически настраивать размеры ваши компоненты, чтобы он правильно отображался за пределами вашей конкретной среды разработки.

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

Кстати, если вы разочаровались в стандартных менеджерах компоновки, есть много хороших бесплатных сторонних разработчиков с открытым исходным кодом, например, JGoodies 'FormLayout , или MigLayout. Некоторые сборщики GUI даже имеют встроенную поддержку сторонних менеджеров компоновки - например, редактор GUI Windowclipder от Eclipse поставляется с поддержкой FormLayoutи MigLayout.

Джейсон С
источник
2
+1 внимательный ответ - просто не согласен с тем, что они не являются злыми по своей сути просто потому, что они :-) Обычно внешние клиенты не имеют никаких шансов угадать - а простые предположения настолько близки, насколько посторонние могут получить - наполовину правильные подсказки макета: только Сами компоненты всегда имеют всю информацию, чтобы вернуть что-нибудь полезное. И с того момента, как посторонние лица вмешиваются, они обязаны постоянно обновлять эти подсказки, чего они не могут.
Клеопатра
1
Ну, вы знаете, у меня есть вид "оружие не убивает людей, люди убивают людей", вид такого рода вещей. :) Если кто-то использует эти методы, он должен знать о положительных моментах, которые вы поднимаете, о непредсказуемом использовании подсказок макета (вот почему ситуации, когда эти методы подходят, действительно редки).
Джейсон С
Я думаю, что установка предпочтительного размера совсем не большой красный флаг. Не устанавливая это является большим красным флагом вместо этого. Позвольте мне уточнить. Менеджер по расположению - независимо от того, насколько он умен - не имеет представления о логической функции графического интерфейса. Например, менеджер компоновки не может различить JTextField для ввода почтового индекса и JTextField для ввода имени. Точно так же он не может различить кнопку инструмента рядом с JTextField или большую кнопку ОК внизу формы. Поэтому или лучший набор виджетов, или нужны некоторые подсказки по размеру, нет?
Джи Би
@GeeBee Нет, на самом деле это яркий пример красного флага. То, что вы должны сделать, это использовать JTextField.setColumnsдля установки количества столбцов, которое соответственно изменяет предпочтительный размер. Если вы это сделаете, setPreferredSizeто вы жестко закодируете размер, который нарушит ваши макеты в зависимости от размера шрифта платформы. Вот некоторые текстовые поля в макете мешка сетки с setColumnsсоответствующим названием . Для ваших кнопок используйте соответствующие макеты / веса сетки для контроля размеров.
Джейсон C
@GeeBee И теперь, когда все сделано правильно, обратите внимание, как уменьшается ширина текстового поля при уменьшении размера шрифта: i.snag.gy/ZULulh.jpg . Даже изменение размера шрифта на лету теперь работает автоматически, вместо того, чтобы вам, скажем, приходилось пересчитывать всю ширину текстового поля и явно вызывать setPreferredSize для каждого, все, что вам нужно сделать, это сделать макет недействительным, и их размеры будут скорректированы.
Джейсон С
20

Если у вас возникли проблемы с раскладками в Java Swing, то я очень рекомендую JGoodies FormLayoutпредоставляемое свободно в рамках форм бесплатной библиотеки Карстен Lentzsch здесь .

Этот очень популярный менеджер макетов чрезвычайно гибок, что позволяет разрабатывать очень отлаженные пользовательские интерфейсы Java.

Вы найдете документацию Karsten здесь , и некоторые довольно хорошие документы от затмения здесь .

Том
источник
16

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

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

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

Я скажу, что вы не должны пытаться давать подсказки менеджера компоновки с этими методами, пока вы не уверены, что они вам нужны. Сделайте макет, не давая никаких подсказок по размеру (т.е. позвольте менеджеру макета делать свою работу), и тогда вы можете внести незначительные исправления, если вам нужно.

Майкл
источник
1
либо есть небольшое заблуждение (с вашей стороны) или недопонимание (с моей стороны), возьмите свой выбор :-) Вы продолжаете повторять (здесь, в блоге, в своем ответе в связи с BoxLayout) на множестве XXSize как быть важным - на самом деле LayoutManager (или нет) интересуется размером XXSize, то есть подсказкой по размерам, не зависящей от того, как она возникла (внутренний расчет компонентом или принудительно вручную с помощью кода приложения)
kleopatra
1
Я не уверен, что понимаю, что вы получаете здесь. Я упомянул выше, что методы XXSize () являются лишь подсказками. Я действительно не вижу ничего плохого в том, чтобы дать менеджеру макета небольшую подсказку, если это необходимо. В моем свинг-коде вы найдете случайный метод setXXSize (). Не много, но время от времени я нахожу, что они необходимы. JComboBox и JSpinner часто нуждаются в подсказках. Особенно JComboBox, который заполняется после его реализации. Вы, кажется, против любого и любого использования этих методов, и я не знаю почему. (может быть, я один скучаю по лодке в этом, я думаю).
Майкл
5
не методы - это подсказки, а свойства : компоненты должны сообщать что-то разумное для всех подсказок, а некоторые (как например, JComboBox) - возвращая maxInteger или около того. Это ошибка и должна быть исправлена ​​комбо. Что касается вашей привычки: будьте уверены, что будете далеко, когда коллеге по сопровождению придется это исправить :). Жестко запрограммированные подсказки имеют тенденцию разрушать макет при малейших изменениях, и его трудно обнаружить в качестве причины сломанного макета.
Клеопатра
15

В ситуации, когда мне нужно определить пропорции между дочерними элементами компонента (дочерний элемент 1 должен использовать 10% пространства, дочерний2 40%, дочерний 3 50%), возможно ли достичь этого без применения настраиваемого менеджера компоновки?

Может быть GridBagLayout, удовлетворит ваши потребности. Кроме того, в сети есть куча менеджеров компоновки, и я уверен, что есть тот, который соответствует вашим требованиям.

Томас
источник
Спасибо за ответ. Я должен предположить, что вы имели в виду также: «вообще не используйте setPreferredSize», верно?
Гейзенбаг
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 символов, но может увеличиваться до большего при изменении размера макета, поэтому установите максимальный размер больше. В то же время иметь JTextField шириной 0px бессмысленно, поэтому установите реалистичный минимальный размер (я бы сказал, размер пикселя 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 находился на двух дисплеях на экране. настройка нескольких дисплеев).

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

Вы можете использовать JSplitPane, где вы можете предварительно установить соотношение двух сторон. Или вы можете использовать MigLayout, который позволяет вам устанавливать такие ограничения в процентах, пикселях и других единицах.

Джи Би
источник
В самом деле? Это было в 0? Это лучше, чем принятый ответ, который имеет более 100 взлетов. Это в основном говорит: «Ты должен Невар использовать setPreferredSize!» который ужасен. В моей работе много требований к размеру, таких как «Кнопки на сенсорных экранах должны быть [X] на [Y] с интервалом [M] x [N] между» ». btnBar.setPreferredSize( dimTouchBtn );это лучший способ сделать это. Просто, нет необходимости в настраиваемом менеджере компоновки. Я использую в основном GridBagLayoutс некоторыми BorderLayoutи BoxLayout, когда это удобно. Это сильная комбинация и проста в использовании.
Лодувийк
Я был поспешен в моем комментарии выше. Это был первый ответ, который я увидел после принятого ответа. Почему ТАК больше не сортирует по количеству голосов? Я думал, что это было одной из основных причин подсчета голосов изначально. Я все еще поддерживаю оригинальный комментарий; это один из лучших ответов. За исключением пункта № 6 - этот не так велик. Есть много причин (меньшинство все еще может быть большим) причин для изменения размера, и GridBagLayout хорошо поддерживает это в большинстве случаев, которые у меня были.
Лодувийк
Я думаю, что изменение размера против не изменения размера не должно рассматриваться как религиозное решение. Бывают случаи, когда никто не хочет что-либо изменять, например, если вы разрабатываете графический интерфейс для киоска с предустановленным фиксированным разрешением. Если у вас разные цели, такие как промышленные дисплеи HMI и корпус «кнопок», то да, вам нужно иметь по крайней мере 1 см на 1 см для кнопки на сенсорном экране. В этом случае DPI экрана определяет, как вы изменяете размер. Другие входные данные, такие как текстовые поля, могут вообще не изменять размер по вертикали, а иногда (например, почтовый индекс) горизонтальное изменение также не имеет смысла.
Джи Би
0

Должен ли я полностью избегать использования этих методов? Я бы не сказал «избегать» их. Я бы сказал, что если вы думаете, что они вам нужны, вы, вероятно, делаете что-то не так. Размеры компонентов определяются в контексте. Например, размеры текстового компонента определяются указанным количеством строк и столбцов в сочетании с выбранным вами шрифтом. Размер вашей кнопки и метки будет соответствовать размеру графического изображения, если вы его установили, или месту, необходимому для отображения заданного вами текста. Каждый компонент имеет естественный размер, и менеджеры компоновки будут использовать его для разметки всего, без необходимости указывать размеры. Основным исключением является JScrollPane, размер которого не зависит от содержимого. Для них я иногда буду звонить setSize(), и пусть этот размер определяет начальный размер окна, вызываяJFrame.pack(), Обычно я позволяю размеру окна определять размер JScrollPane. Пользователь определит размер окна. Многие менеджеры компоновки игнорируют установленные вами размеры, поэтому они часто не приносят пользы.

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

Каковы конкретно негативные последствия использования этих методов? (Я могу только подумать о добавлении переносимости между системами с разным разрешением экрана). Они неэффективны и создают плохие макеты, при этом объекты сжимаются или растягиваются до неестественных размеров. И макеты будут хрупкими. Изменения в размере окна иногда нарушают компоновку и помещают вещи в неправильные места.

Я не думаю, что любой LayoutManager может точно удовлетворить все желаемые потребности макета. Действительно ли мне нужно реализовывать новый LayoutManager для каждого небольшого изменения моего макета? Вы не должны «реализовывать» новый LayoutManager. Вы должны создать экземпляр существующих. Я часто использую несколько менеджеров компоновки в одном окне. Каждый JPanel будет иметь свой собственный менеджер макета. Некоторые люди отказываются от вложенных макетов, потому что их сложно поддерживать. Когда я их использую, я даю каждому свой метод создания, чтобы было легче увидеть, что делает каждый. Но я никогда не «внедряю» менеджер раскладок. Я просто создаю их экземпляр.

Если ответ на 4 «да», не приведет ли это к увеличению числа классов LayoutManager, которые будет трудно поддерживать? Если вы реализуете новые классы менеджера компоновки для небольших изменений в компоновке, вы используете их неправильно. Если вы просто внедряете новые менеджеры компоновки, вы, вероятно, делаете что-то не так. Единственный раз, когда я расширил класс LayoutManager, это было добавить ползунок масштабирования в JScrollPane.

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

MiguelMunoz
источник