Поиск общего метода для создания компонентов GridBagLayout

Я разрабатываю графический интерфейс с 20 компонентами: 10 ярлыков, 4 текстовых поля, 4 кнопки и 2 текстовые области. Использование GridBagLayout показалось отличной идеей. Но со всеми переменными экземпляра, необходимыми для этого по книге для каждого компонента (т. Е. Не для повторного использования), общий метод добавления компонентов казался обязательным. Я действительно думал, что это может сработать:

(Примечание: HORIZ является аббревиатурой для GridBagConstraints.HORIZONTAL; CENTER является аббревиатурой для GridBagConstraints.CENTER.)

public static void addComponent(Container f, Component c, int x, int y, int w, int h, int ipadx, int ipady, float wtx, float wty, int fill, int anchor, Insets insets){ GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = x; gbc.gridy = y; gbc.gridwidth = w; gbc.gridheight = h; gbc.fill = fill; gbc.ipadx = ipadx; gbc.ipady = ipady; gbc.insets = insets; gbc.anchor = anchor; gbc.weightx = wtx; gbc.weighty = wty; f.add(c,gbc); } 

Я назвал это так:

  Insets insets = new Insets(0,0,0,0); JFrame frame = new JFrame(); label = new JLabel("Blablablah"); addComponent(frame, label, 0,0, 1,1, 0,0, 0.5f,0, HORIZ, CENTER, insets); 

Но я получил сообщение «не могу добавить в макет: ограничение должно быть строкой (или нулевой)» на f.add(c.gbc) .

Я думаю, что я понимаю ошибку: в frame нет GridBagConstraints до вызова addComponent и gbc в первой строке метода не принадлежит параметру f (или что-нибудь еще?).

Поэтому я слегка модифицировал подпись метода, опуская Container :

 public static void addComponent( Component c, int x, int y, ... (rest unchanged) 

И я изменил проблемную строку следующим образом:

 frame.add(c, gbc); 

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

Два вопроса:

(1) Есть ли способ минимально изменить мой код, чтобы включить передачу frame в addComponent ?

(2) Есть ли основания для этого? Наверное, это вопрос к тому, что бы вы сделали?


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

 private static void createAndShowGUI() { GUI = new JFrame(); GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); gbl = new GridBagLayout(); GUI.setLayout(gbl); addComponent(lblRootNode, 0,0, 1,1, 0,0, 0.5f,0, HORIZONTAL, CENTER, new Insets(0,0,0,0)); addComponent(txtRootNode, 1,0, 5,1, 60,0, 0.5f,0, HORIZONTAL, CENTER, new Insets(0,0,0,0)); addComponent(btnBrowse, 6,0, 1,1, 0,0, 0.5f,0, HORIZONTAL, CENTER, new Insets(0,0,0,0)); addComponent(lblFilenamePat, 0,1, 2,1, 0,0, 0.5f,0, HORIZONTAL, EAST, new Insets(0,0,0,0)); addComponent(txtFilenamePat, 2,1, 4,1, 0,0, 0.5f,0, HORIZONTAL, LINE_END, new Insets(0,0,0,0)); addComponent(lblDates, 0,2, 2,1, 0,0, 0.5f,0, HORIZONTAL, CENTER, new Insets(0,0,0,0)); addComponent(lblSizes, 2,2, 2,1, 0,0, 0.5f,0, HORIZONTAL, CENTER, new Insets(0,0,0,0)); 

Я довольно часто использую GridBagLyout, но, как и многие другие передо мной, я быстро обнаружил, что это может быть довольно многословным. В Интернете есть много примеров того, как пользователи написали методы и / или classы, чтобы помочь им генерировать код GBL. Я покажу вам, что я делаю.

1) Во-первых, я создал 2 enums, которые являются обертками для привязки и заполняют поля GridBagConstraints. Я предпочитаю проверку типов enums vs. ints, а также позволяет писать более сжатый код (как вы увидите ниже). И да, я все еще использую более старые «направленные» значения для Anchor. Я никогда не мог привыкнуть к предпочтительным значениям PAGE_START и тому подобное. Используйте все, что вы предпочитаете.

Anchor.java:

 пакет gbl;

 import java.awt. *;

 / **
  * Удобное перечисление, которое выдает все возможные значения для
  * Свойство привязки GridBagConstraints.
  * /
 public enum Anchor
 {
   СЕВЕР (GridBagConstraints.NORTH),
   ЮГ (GridBagConstraints.SOUTH),
   ИСТ (GridBagConstraints.EAST),
   Запад (GridBagConstraints.WEST),
   СЕВЕРО (GridBagConstraints.NORTHEAST),
   СЕВЕРО (GridBagConstraints.NORTHWEST),
   Юго-Восток (GridBagConstraints.SOUTHEAST),
   ЮГО (GridBagConstraints.SOUTHWEST),
   CENTER (GridBagConstraints.CENTER);

   ограничение частного int;

   private Anchor (int gbConstraint)
   {
     constraint = gbConstraint;
   }

   public int getConstraint ()
   {
     ограничение возврата;
   }
 }

Fill.java:

 пакет gbl;

 import java.awt. *;

 / **
  * Удобное перечисление, которое выдает все возможные значения для
  * GridBagConstraints заполняет свойство.
  * /
 public enum Fill
 {
   NONE (GridBagConstraints.NONE),
   ГОРИЗОНТАЛЬНЫЙ (GridBagConstraints.HORIZONTAL),
   ВЕРТИКАЛЬНЫЙ (GridBagConstraints.VERTICAL),
   ОБА (GridBagConstraints.BOTH);

   ограничение частного int;

   private Fill (int gbConstraint)
   {
     constraint = gbConstraint;
   }

   public int getConstraint ()
   {
     ограничение возврата;
   }
 }

2) Затем я создал подclass GridBagConstraints, который позволил мне «привязать» свойства только так, как они мне нужны, используя общие значения по умолчанию:

GBConstraints.java:

 пакет gbl;

 import java.awt. *;

 / **
  * Класс удобства для упрощения создания объекта GridBagConstraints.
  * /
 Открытый class GBConstraints расширяет GridBagConstraints
 {
   public GBConstraints (int gridX, int gridY)
   {
     супер();

     this.gridx = gridX;
     this.gridy = gridY;

     this.gridwidth = 1;
     this.gridheight = 1;
     this.weightx = 0;
     this.weighty = 0;
     this.anchor = NORTHWEST;  // старое значение по умолчанию - CENTER
     this.fill = NONE;
     this.insets = новые вставки (1,2,1,2);  // старое значение по умолчанию было (0,0,0,0)
     this.ipadx = 1;  // old default был 0
     this.ipady = 1;  // old default был 0
   }

   публичный якорь GBConstraints (якорный якорь)
   {
     this.anchor = anchor.getConstraint ();
     верните это;
   }

   публичная заливка GBConstraints (заполнение заполнения)
   {
     this.fill = fill.getConstraint ();

     / *
      * В качестве удобства установите весы соответствующим образом, поскольку эти значения
      * почти всегда используется в тандеме с данным заполнением.  Вызывающий может всегда
      * вызов метода веса (...) позже, если эти значения по умолчанию не требуются. 
      * /
     переключатель (заполнение)
     {
       case HORIZONTAL:
         this.weightx = 1;
         this.weighty = 0;
         ломать;
       case VERTICAL:
         this.weightx = 0;
         this.weighty = 1;
         ломать;
       case ОБА:
         this.weightx = 1;
         this.weighty = 1;
         ломать;
       по умолчанию:
         this.weightx = 0;
         this.weighty = 0;
         ломать;
     }

     верните это;
   }

   общедоступные вставки GBConstraints (int length)
   {
     возвратные вставки (длина, длина, длина, длина);
   }

   общедоступные вставки GBConstraints (int top, int left, int bottom, int right)
   {
     this.insets = new Insets (верхний, левый, нижний, правый);
     верните это;
   }

   public GBConstraints ipad (int ipadX, int ipadY)
   {
     this.ipadx = ipadX;
     this.ipady = ipadY;
     верните это;
   }

   public GBConstraints span (int gridWidth, int gridHeight)
   {
     this.gridwidth = gridWidth;
     this.gridheight = gridHeight;
     верните это;
   }

   public GBConstraints spanX (int gridWidth)
   {
     this.gridwidth = gridWidth;
     верните это;
   }

   public GBConstraints spanY (int gridHeight)
   {
     this.gridheight = gridHeight;
     верните это;
   }

   общий вес GBConstraints (двойной весX, двойной весY)
   {
     this.weightx = weightX;
     this.weighty = weightY;
     верните это;
   }

   публичный GBConstraints weightX (double weightX)
   {
     this.weightx = weightX;
     верните это;
   }

   публичный GBConstraints weightY (двойной весY)
   {
     this.weighty = weightY;
     верните это;
   }
 }

3) Объединяя все это, вот демо, показывающее, как использовать вышеуказанные classы. Это значительно упрощает использование GridBagLayout, IMHO. Боковое замечание: я обычно держался подальше от статического импорта, но мне нравится в этой ситуации.

Демоверсия:

 пакет gbl;

 import static gbl.Anchor. *;
 import static gbl.Fill. *;

 import java.awt. *;
 import javax.swing. *;

 Открытый class GridBagDemo реализует Runnable
 {
   public static void main (String [] args)
   {
     SwingUtilities.invokeLater (новый GridBagDemo ());
   }

   public void run ()
   {
     JLabel lblFirst = новый JLabel («Имя»);
     JLabel lblLast = новый JLabel («Фамилия»);
     JLabel lblStreet = новый JLabel («Улица»);
     JLabel lblCity = новый JLabel («Город»);
     JLabel lblState = новый JLabel («Состояние»);
     JLabel lblZip = новый JLabel («ZIP»);
     JLabel lblNotes = новый JLabel («Заметки»);

     JTextField txfFirst = новый JTextField (15);
     JTextField txfLast = новый JTextField (20);
     JTextField txfStreet = новый JTextField (40);
     JTextField txfCity = новый JTextField (15);
     JTextField txfState = новый JTextField (5);
     JTextField txfZip = новый JTextField (10);

     JTextArea txaNotes = новый JTextArea (5, 50);
     JScrollPane scrNotes = новый JScrollPane (txaNotes);
     scrNotes.setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

     Компонент spacer1 = Box.createHorizontalStrut (5);
     Компонент spacer2 = Box.createHorizontalStrut (5);

     Панель JPanel = новый JPanel (новый GridBagLayout ());
     panel.add (spacer1, новые GBConstraints (0,0));
     panel.add (lblFirst, новые GBConstraints (0,1));
     panel.add (txfFirst, новые GBConstraints (1,1));
     panel.add (lblLast, новые GBConstraints (2,1));
     panel.add (txfLast, новые GBConstraints (3,1) .spanX (3) .fill (HORIZONTAL));
     panel.add (lblStreet, новые GBConstraints (0,2));
     panel.add (txfStreet, новые GBConstraints (1,2) .spanX (5) .fill (HORIZONTAL));
     panel.add (lblCity, новые GBConstraints (0,3));
     panel.add (txfCity, новые GBConstraints (1,3));
     panel.add (lblState, новые GBConstraints (2,3) .anchor (EAST));
     panel.add (txfState, новые GBConstraints (3,3));
     panel.add (lblZip, новые GBConstraints (4,3));
     panel.add (txfZip, новые GBConstraints (5,3) .fill (HORIZONTAL));
     panel.add (lblNotes, новые GBConstraints (0,4));
     panel.add (scrNotes, новые GBConstraints (1,4) .spanX (5) .fill (BOTH));
     panel.add (spacer2, новый GBConstraints (0,5));

     JFrame frame = новый JFrame («Сетка с сумкой»);
     frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
     frame.add (новый JScrollPane (панель), BorderLayout.CENTER);
     frame.pack ();
     frame.setLocationRelativeTo (нуль);
     frame.setVisible (истина);
   }
 }

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

Ты сказал:

Я назвал это так:

 Insets insets = new Insets(0,0,0,0); JFrame frame = new JFrame(); label = new JLabel("Blablablah"); addComponent(frame, label, 0,0, 1,1, 0,0, 0.5f,0, HORIZ, CENTER, insets); 

Вы действительно frame.setLayout(new GridBagLayout()) ?
Поскольку это то, что вызывает cannot add to layout: constraint must be a string (or null) ошибкой …

РЕДАКТИРОВАТЬ:
Возможные дубликаты:

  • Java GridBagLayout и JPanel Ошибка: нельзя добавить в макет: ограничение должно быть строкой (или нулевой)
  • получение Исключение: java.lang.IllegalArgumentException: нельзя добавить в макет: ограничение должно быть строкой (или нулевым)

Как я уже отмечал выше, помощь @ ccjmme побудила меня добавить две строки и изменить подпись, чтобы получить рабочую версию без глобальных переменных. Я публикую версию, которая намного лучше, чем рабочая версия. Мой последующий комментарий объясняет, почему.

 package test; import java.awt.*; import javax.swing.*; public class Test{ public static void addComponent(Component c, Container f, GridBagConstraints gbc, int x, int y, int w, int h, int ipadx, int ipady, float wtx, float wty, int fill, int anchor, Insets insets){ if(fill <= 0) fill = GridBagConstraints.NONE; if(anchor <= 0) anchor = GridBagConstraints.CENTER; if(insets == null) insets = new Insets(0,0,0,0); gbc.gridx = x; gbc.gridy = y; gbc.gridwidth = w; gbc.gridheight = h; gbc.fill = fill; gbc.ipadx = ipadx; gbc.ipady = ipady; gbc.insets = insets; gbc.anchor = anchor; gbc.weightx = wtx; gbc.weighty = wty; f.add(c,gbc); } public static void addComponent(String s, Container f, GridBagConstraints gbc, int x, int y, int w, int h, int ipadx, int ipady, float wtx, float wty, int fill, int anchor, Insets insets){ addComponent(new JLabel(s),f,gbc,x,y,w,h,ipadx,ipady,wtx,wty,fill,anchor,insets); } public static void addComponent(Component c, Container f, GridBagConstraints gbc, int x, int y){ addComponent(c, f, gbc, x, y, 1,1, 0,0, 0.5f,0.5f, GridBagConstraints.NONE, GridBagConstraints.CENTER, new Insets(0,0,0,0)); } public static void main(String[] args) { Insets insets = new Insets(0,0,0,0); JFrame frame = new JFrame(); frame.setLayout(new GridBagLayout()); JLabel label = new JLabel("Blablablah"); JTextField text = new JTextField("text"); JTextField next = new JTextField("a bit longer"); GridBagConstraints gbc = new GridBagConstraints(); addComponent("On the fly", frame, gbc, 0,0, 1,1, 0,0, 0.5f,0, 0, 0, insets); addComponent(label, frame, gbc, 0,1); addComponent(next, frame, gbc, 1,1, 10,1, 0,0, 5.0f,0.5f, GridBagConstraints.EAST, 0, null); addComponent(text, frame, gbc, 1,0); frame.pack(); frame.setVisible(true); } } 

Улучшения:

(1) Две дополнительные подписи для addComponent так что (i) метка может быть создана «на лету» без объявления и инициализации переменной (не хорошо, если код должен ссылаться на нее, но мой редко делает), и (ii) любой компонент может добавляется путем указания (x, y) и принятия значений по умолчанию.

(2) «По умолчанию 0», чтобы избежать необходимости вводить «GridBagConstraints.CENTER and ... NONE», если вам обычно нужны эти значения заполнения и привязки.

Вот я, используя enums и методы @ Splungebob (и его «демо» в качестве модели), чтобы безболезненно и быстро разработать и внедрить очень приятный интерфейс в существующую мою программу, которая имела ужасный интерфейс.

 public class UI extends JFrame { ... JPanel panel = new JPanel(new GridBagLayout()); panel.setBackground(Color.LIGHT_GRAY); panel.add(lblCenterX, new GBConstraints(0,0)); panel.add(lblCenterY, new GBConstraints(0,1)); panel.add(lblRadius, new GBConstraints(0,2).anchor(EAST)); panel.add(lblIterations, new GBConstraints(0,3).anchor(EAST)); panel.add(spnCenterX, new GBConstraints(1,0).fill(HORIZONTAL)); panel.add(spnCenterY, new GBConstraints(1,1).ipad(90,10)); panel.add(spnRadius, new GBConstraints(1,2)); panel.add(spnIterations, new GBConstraints(1,3)); panel.add(btnPaint, new GBConstraints(0,4).spanX(2).spanY(2).ipad(30,20).anchor(CENTER)); panel.add(btnDefaults, new GBConstraints(0,6)); panel.add(btnExit, new GBConstraints(1,6).anchor(EAST)); this.add(panel, BorderLayout.CENTER); this.pack(); this.setLocationRelativeTo(null); this.setVisible(true); 

Я публикую это только в надежде, что кто-то нуждается в такой же помощи, как и в GBL, найдет ее, а затем снова оглянется на вещи Сплинга. Как круто линия для btnPaint , где я делаю ОГРОМНУЮ кнопку!

  • Как установить изображение в качестве фона для фрейма в Swing GUI java?
  • Как установить значок в столбце JTable?
  • Структура каталогов Java JTree из путей к файлам
  • Обнаружение ввода нажмите в JTextField
  • добавление индикатора выполнения для каждой ячейки таблицы для прогресса файла - Java
  • Установка максимального размера JDialog?
  • Использование JInternalFrame и некоторой кнопки
  • Сделать JScrollPane управление несколькими компонентами
  • CombinedDomainXYPlot не перемасштабирует доменную ось
  • Путаница обнаружения столкновений прямоугольника Java
  • JMenuItem ImageIcon слишком большой
  • Interesting Posts

    Модульный ввод / вывод файлов

    Магический номер в boost :: hash_combine

    Как запустить onListItemClick в Listactivity с помощью кнопок в списке?

    Почему мой localhost не 127.0.0.1, а :: 1, и что это за нотация?

    В чем разница между (типом) значением и типом (значением)?

    Не удалось загрузить файл или сборку «Microsoft.ReportViewer.Common, Version = 11.0.0.0

    В чем разница между «uname -r» и «uname -v»?

    Что делать с настройками реестра DVD / DVD-драйверов LowerFilters и UpperFilters?

    Введите ключевой обработчик события

    Как найти мои предыдущие IP-адреса

    Разве это не на больших байтовых машинах UTF-8, отличных от маленьких конечных машин? Так почему же тогда UTF-8 не требует спецификации?

    Могу ли я установить Windows 7 в именах A: \ или B: \?

    Как переустановить Windows 10 на новый жесткий диск

    Как настроить мой ADSL-модем и домашний компьютер для доступа к внешним устройствам?

    Попытка изменить пароль пользователя Ubuntu, ошибка манипулирования аутентификацией аутентификации

    Давайте будем гением компьютера.