Должен ли я избегать использования методов set (Preferred | Maximum | Minimum) в Java Swing?

Несколько раз меня критиковали за то, что предложили использовать следующие методы:

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

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

С макетами ответ всегда один и тот же: используйте подходящий LayoutManager

Я немного искал в Интернете, но я не нашел всестороннего анализа этого вопроса. Поэтому у меня есть следующие вопросы:

  1. Должен ли я полностью избегать использования этих методов?
  2. Методы были определены по определенной причине. Итак, когда я должен их использовать? В каком контексте? Для каких целей?
  3. Каковы же отрицательные последствия использования этих методов? (Я могу только думать о добавлении переносимости между системами с различным разрешением экрана).
  4. Я не думаю, что любой LayoutManager может точно удовлетворить все требуемые потребности макета. Действительно ли мне нужно реализовать новый LayoutManager для каждого небольшого варианта моего макета?
  5. Если ответ на вопрос 4 «да», не приведет ли это к разрастанию classов LayoutManager, которые станут трудно поддерживать?
  6. В ситуации, когда мне нужно определить пропорции между дочерними элементами компонента (например, child1 должен использовать 10% пространства, child2 40%, child3 50%), можно ли достичь этого без реализации пользовательского LayoutManager?

Надеюсь, что было ясно.

  1. Должен ли я полностью избегать использования этих методов?

    Да для кода приложения.

  2. Методы были определены по определенной причине. Итак, когда я должен их использовать? В каком контексте? Для каких целей?

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

  3. Каковы же отрицательные последствия использования этих методов? (Я могу только думать о добавлении переносимости между системами с различным разрешением экрана.)

    Некоторые (неполные и, к сожалению, ссылки не работают из-за миграции SwingLabs на java.net), технические причины, например, упоминаются в Правилах (хехе) или в ссылке @bendicott, найденной в его комментарии к моему ответу . Социально, создавая тонны работы над вашим несчастным парнем, который должен поддерживать код и должен отслеживать сломанный макет.

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

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

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

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

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

    Любой из «Большой тройки» может даже не 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 размера, например 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 https://stackoverflow.com/questions/7229226 * @see https://stackoverflow.com/questions/7228843 */ public class DesignTest { private List list = new ArrayList(); 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()); } } } } 

Должен ли я полностью избегать использования этих методов?

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

Они также могут быть переопределены (что является лучшей практикой для Swing) при расширении компонента Swing (вместо вызова метода на экземпляре пользовательского компонента)

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

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

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

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

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

  • Убедитесь, что вам действительно нужно установить точный размер компонента. Каждый компонент Swing имеет другой предпочтительный размер, в зависимости от используемого шрифта и внешнего вида. Таким образом, наличие заданного размера может приводить к различным аспектам пользовательского интерфейса в разных системах

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

  • JFrame не getMinimumSize() overriden getMinimumSize() только вызывающий setMinimumSize(..) в своих работах

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

Если при реализации вы имеете в виду использование тогда да. Ни один LayoutManger может справиться со всем, у каждого LayoutManager есть свои плюсы и минусы, поэтому каждый может использоваться вместе для создания окончательной компоновки.

Справка:

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

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

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

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

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

Кстати, если вы разочаровываетесь со стандартными менеджерами макетов, есть много хороших бесплатных сторонних разработчиков с открытым исходным кодом, например, JLoodies FormLayout или MigLayout . Некоторые разработчики графического интерфейса даже имеют встроенную поддержку сторонних менеджеров компоновки – редактор GUI WindowBuilder от Eclipse, например, поставляется с поддержкой FormLayout и MigLayout .

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

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

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

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

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

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

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

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

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

Я вижу это иначе, чем принятый ответ.

1) Должен ли я полностью избегать использования этих методов?

Никогда не избегайте! Они могут выражать ограничения размера ваших компонентов в менеджере компоновки. Вы можете избежать их использования, если вы не используете какой-либо менеджер макетов и не пытаетесь самостоятельно управлять визуальным макетом.

К сожалению, Swing не идет с разумными размерами по умолчанию. Однако вместо того, чтобы устанавливать размеры компонента, лучше OOP опускать ваш собственный компонент с разумными значениями по умолчанию. (В этом случае вы вызываете setXXX в свой class потомков.) В качестве альтернативы вы можете переопределить методы getXXX для того же эффекта.

2) Методы были определены по определенной причине. Итак, когда я должен их использовать? В каком контексте? Для каких целей?

Всегда. Когда вы создаете компонент, установите его реалистичный минимальный / предпочтительный / максимальный размер в соответствии с использованием этого компонента. Например, если у вас есть JTextField для ввода символов страны, таких как Великобритания, его предпочтительный размер должен быть таким же широким, чтобы соответствовать двум символам (с текущим шрифтом и т. Д.), Но, вероятно, бессмысленно позволять ему расти больше. В конце концов, символы страны – это два символа. Как противоположность, если у вас есть JTextField для ввода, например, имя клиента, он может иметь предпочтительный размер, например размер пикселя для 20 символов, но может увеличиться до размера, если размер макета будет изменен, поэтому установите максимальный размер на большее. В то же время, имея широкоугольный JTextField с шириной 0px, задается реалистичный минимальный размер (я бы сказал, размер пикселя 2 символа).

3) В чем именно негативные последствия использования этих методов?

(Я могу только думать о добавлении переносимости между системами с различным разрешением экрана).

Никаких негативных последствий. Это подсказки для менеджера компоновки.

4) Я не думаю, что любой LayoutManager может точно удовлетворить все требуемые потребности макета.

Действительно ли мне нужно реализовать новый LayoutManager для каждого небольшого варианта моего макета?

Нет, определенно нет. Обычный подход состоит в том, чтобы каскадировать различные базовые макеты, такие как горизонтальная и вертикальная компоновка.

Например, макет ниже:

 
 +--------------+--------+ | ###JTABLE### | [Add] | | ...data... |[Remove]| | ...data... | | | ...data... | | +--------------+--------+ 

имеет две части. Левая и правая части – горизонтальная компоновка. Правая часть – JPanel, добавленная к горизонтальной компоновке, и эта JPanel имеет вертикальную компоновку, которая выставляет кнопки по вертикали.

Конечно, это может стать сложным с реалистичным макетом. Поэтому сетевые менеджеры макетов, такие как MigLayout, намного лучше, если вы собираетесь разработать что-то серьезное.

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

Нет, вы определенно не должны разрабатывать менеджеров макетов, если вам не нужно что-то особенное.

6) В ситуации, когда мне нужно определить пропорции …

между дочерними элементами компонента (например, child1 должен использовать 10% пространства, child2 40%, child3 50%), можно ли достичь этого без реализации пользовательского LayoutManager?

В принципе, как только предпочтительные размеры будут установлены правильно, вы можете не захотеть ничего делать в процентах. Просто потому, что проценты бессмысленны (например, бессмысленно иметь JTextField 10% от размера windows, поскольку можно сжать окно так, чтобы JTextField стал шириной 0px или мог расширить окно, чтобы JTextField находился на двух дисплеях на мульти-дисплей).

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

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

  • Добавление jRadioButton в jTable
  • Получение состояния JToggleButton
  • Как использовать SwingWorker?
  • Cytoscape как инструменты в java для построения графика
  • JTable + Сортировка определенного поля
  • Фоновое изображение JFrame
  • Как отменить выполнение SwingWorker?
  • Имея изображения в качестве фона JPanel
  • JTable Calls Custom Cell Renderer Method ... Непрерывно
  • Использование addMouseListener () и paintComponent () для JPanel
  • Как изменить цвет конкретных слов в JTextPane?
  • Давайте будем гением компьютера.