Часто когда начинаешь работать на SWING сталкиваешься с проблемой понимания Layout.
Сама идея очень хорошая, но для людей которые работали только в визуальных средах это становится большой проблемой. Не может человек понять почему быстрее написать код чем накидать его в GUI дизайнере. Сам я со свингом плотно работаю около 2 лет и вот решил рассказать про замечательную библиотеку JGoodies Form Layout. Статей наверное пока будет только три, если все хорошо буду писать дальше.
И так часть первая вводная.
В данном примере мы рассмотрим базовые возможности Form Layout. FormLayout — это фактически таблица, только с очень гибкими настройками, благодаря им можно получить любой интерфейс с минимальными затратами.
Рассмотрим простую задачу
Хотим сделать вот такое окно
Решение с помощью FormLayout
1: FormLayout layout = new FormLayout(
2: “pref, 4dlu, 50dlu, 4dlu, min”, // столбцы
3: “pref, 2dlu, pref, 2dlu, pref”); // строки
4:
5: layout.setRowGroups(new int[][]{{1, 3, 5}});
6:
7: JPanel panel = new JPanel(layout);
8:
9: CellConstraints cc = new CellConstraints();
10: panel.add(new JLabel(“Label1”), cc.xy (1, 1));
11: panel.add(textField1, cc.xyw(3, 1, 3));
12: panel.add(new JLabel(“Label2”), cc.xy (1, 3));
13: panel.add(textField2, cc.xy (3, 3));
14: panel.add(new JLabel(“Label3”), cc.xy (1, 5));
15: panel.add(textField3, cc.xy (3, 5));
16: panel.add(detailsButton, cc.xy (5, 5));
Объясним этот код:
С 1 по 3 строку создаем объект FormLayout и определяем строки и столбцы, нашего layout'а последовательностью двух строк. Значение «pref» определяется как предпочтительный размер(preffered size), иначе говоря размер определяется помещаемым компонентом. Значение «min» определяется как минимальный размер, и последний параметр «dlu» это единица размера зависящая от размера шрифта. На самом деле наборов значений много, практически на любой случай жизни, но здесь я все освещать не буду, подробное описание их можно найти в документации к библиотеке.
Поехали дальше. В строке 5 мы указываем что все компоненты в строках должны быть одинакового размера. В 7 строке мы создаем панельку с нашим FormLayout и в строке 9 мы создаем объект CellConstaraints для расположения компонентов в сетке нашего FormLayout. В конце мы заполняем наш layout элементами интерфейса с использование CellConstraints. Вот так все просто и прозрачно у нас получилось.
Далее я покажу построение более сложного интерфейса. :)
Следующий интерфейс у нас усложнится и будет выглядеть вот так
У читателя наверное возник вопрос что в этим интерфейсе сложного. Первое здесь есть выравнивание по центру, второе при изменении надписей интерфейс не съезжает(+1 к локализации).
И так взглянем на код:
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
/**
*
* author Greg
*/
public class PlaceboSearchDialog extends JFrame {
private JTextField nameField;
private JTextField surnameField;
private JTextField nickName;
private JButton searchButton;
private String[] columnNames = {«Nickname», «Name», «Surname», «Phone»};
private Object[][] data = {{«Vincent», «Andrew», «Gos», "+1 400 789 00 78"},
{«Kitty», «Kate», «Philler», "+1 421 567 89 09"}};
private JTable searchTable;
public PlaceboSearchDialog() {
init();
buildFrame();
}
public void init() {
nameField = new JTextField();
surnameField = new JTextField();
nickName = new JTextField();
searchButton = new JButton(«Search»);
searchTable = new JTable(data, columnNames);
}
public void buildFrame() {
this.setTitle(«Placebo Phonebook»);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
searchTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
searchTable.getColumn(«Phone»).setMinWidth(100);
JScrollPane scrollPane = new JScrollPane(searchTable);
FormLayout layout = new FormLayout(
«right:pref,3dlu,70dlu,3dlu,left:pref:grow»,
«2*(pref,3dlu),fill:pref:grow,3dlu»);
DefaultFormBuilder builder = new DefaultFormBuilder(layout);
builder.setDefaultDialogBorder();
builder.append(«Name», nameField);
builder.nextLine();
builder.nextLine();
builder.append(«Surname», surnameField);
builder.append(searchButton);
builder.nextLine();
builder.nextLine();
builder.append(scrollPane, 5);
this.add(builder.getPanel());
this.setSize(400, 530);
this.setVisible(true);
}
public static void main(String[] args) {
new PlaceboSearchDialog();
}
}
Для построения этого интерфейса я использовал такую полезную вещь как DefaultFormBuilder. Данный builder позволяет отречься от координат и использовать вместо них команды append и nextLine. Помимо этих команд есть nextColumn, nextRow. Выше я использовал CellConstraints для определения место положения компонента. Здесь этот метод только усложнит чтение кода, хотя он и является более гибким, но мы обойдемся и возможностями нашего builder'а. Также из нового здесь добавились параметры такие как «right:pref», «fill:pref:grow», «left:pref:grow».
Данные параметры как вы уже догадались являются составными и могут использоватся как для столбцов так и для строк. Трактуются эти параметры вот так alignment: size: resizeBehavior. Перевод получается как ВЫРАВНИВАНИЕ: РАЗМЕР: ПРОЦЕСС ИЗМЕНЕНИЯ РАЗМЕРА. Например мы в столбец с параметрами left:pref:grow вставили кнопку с названием “Search”, а потом строкой ниже таблицу расширили на все столбцы(builder.append(scrollPane, 5)), так как у столбца стоит параметр «grow», столбец увеличился, но кнопка осталась в нем прежнего размера.
Кстати для проверки моих слов можете заменить строку DefaultFormBuilder builder = new DefaultFormBuilder(layout) на DefaultFormBuilder builder = new DefaultFormBuilder(layout, new FormDebugPanel()). У вас должно получиться в результате вот такое окно:
Красным обведена сетка нашего layout'а, это очень эффективная помощь при отладке интерфейса. В итоге у нас получается очень наглядное представление как будут расположены элементы на экране.
Часто бывает что мы хотим сделать несколько столбцов или строк одного и того же типа. Например нам нужно 5 наборов вот таких столбцов “3dlu,40dlu,3dlu”, для этого чтобы не писать 5 раз один и тот же набор мы можем написать такое выражение
“5*(3dlu,40dlu,3dlu)” вот так просто и красиво.
Теперь коснемся метода builder.append(String label, JComponent component). Данный метод нашего builder'а работает очень хитро, он в первый столбец вставляет JLabel с переданной надписью(пример:builder.append(«Name», nameField) ), потом пропускает один столбец и вставляет уже сам компонент. Такой странный на первый взгляд механизм позволяет очень быстро накидать бизнес формы, а также экономить на ручном создании JLabel'ов.
На этом я заканчиваю статью, следующая будет в понедельник.
Официальный сайт JGoodies
Сама идея очень хорошая, но для людей которые работали только в визуальных средах это становится большой проблемой. Не может человек понять почему быстрее написать код чем накидать его в GUI дизайнере. Сам я со свингом плотно работаю около 2 лет и вот решил рассказать про замечательную библиотеку JGoodies Form Layout. Статей наверное пока будет только три, если все хорошо буду писать дальше.
И так часть первая вводная.
В данном примере мы рассмотрим базовые возможности Form Layout. FormLayout — это фактически таблица, только с очень гибкими настройками, благодаря им можно получить любой интерфейс с минимальными затратами.
Рассмотрим простую задачу
Хотим сделать вот такое окно
Решение с помощью FormLayout
1: FormLayout layout = new FormLayout(
2: “pref, 4dlu, 50dlu, 4dlu, min”, // столбцы
3: “pref, 2dlu, pref, 2dlu, pref”); // строки
4:
5: layout.setRowGroups(new int[][]{{1, 3, 5}});
6:
7: JPanel panel = new JPanel(layout);
8:
9: CellConstraints cc = new CellConstraints();
10: panel.add(new JLabel(“Label1”), cc.xy (1, 1));
11: panel.add(textField1, cc.xyw(3, 1, 3));
12: panel.add(new JLabel(“Label2”), cc.xy (1, 3));
13: panel.add(textField2, cc.xy (3, 3));
14: panel.add(new JLabel(“Label3”), cc.xy (1, 5));
15: panel.add(textField3, cc.xy (3, 5));
16: panel.add(detailsButton, cc.xy (5, 5));
Объясним этот код:
С 1 по 3 строку создаем объект FormLayout и определяем строки и столбцы, нашего layout'а последовательностью двух строк. Значение «pref» определяется как предпочтительный размер(preffered size), иначе говоря размер определяется помещаемым компонентом. Значение «min» определяется как минимальный размер, и последний параметр «dlu» это единица размера зависящая от размера шрифта. На самом деле наборов значений много, практически на любой случай жизни, но здесь я все освещать не буду, подробное описание их можно найти в документации к библиотеке.
Поехали дальше. В строке 5 мы указываем что все компоненты в строках должны быть одинакового размера. В 7 строке мы создаем панельку с нашим FormLayout и в строке 9 мы создаем объект CellConstaraints для расположения компонентов в сетке нашего FormLayout. В конце мы заполняем наш layout элементами интерфейса с использование CellConstraints. Вот так все просто и прозрачно у нас получилось.
Далее я покажу построение более сложного интерфейса. :)
Следующий интерфейс у нас усложнится и будет выглядеть вот так
У читателя наверное возник вопрос что в этим интерфейсе сложного. Первое здесь есть выравнивание по центру, второе при изменении надписей интерфейс не съезжает(+1 к локализации).
И так взглянем на код:
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
/**
*
* author Greg
*/
public class PlaceboSearchDialog extends JFrame {
private JTextField nameField;
private JTextField surnameField;
private JTextField nickName;
private JButton searchButton;
private String[] columnNames = {«Nickname», «Name», «Surname», «Phone»};
private Object[][] data = {{«Vincent», «Andrew», «Gos», "+1 400 789 00 78"},
{«Kitty», «Kate», «Philler», "+1 421 567 89 09"}};
private JTable searchTable;
public PlaceboSearchDialog() {
init();
buildFrame();
}
public void init() {
nameField = new JTextField();
surnameField = new JTextField();
nickName = new JTextField();
searchButton = new JButton(«Search»);
searchTable = new JTable(data, columnNames);
}
public void buildFrame() {
this.setTitle(«Placebo Phonebook»);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
searchTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
searchTable.getColumn(«Phone»).setMinWidth(100);
JScrollPane scrollPane = new JScrollPane(searchTable);
FormLayout layout = new FormLayout(
«right:pref,3dlu,70dlu,3dlu,left:pref:grow»,
«2*(pref,3dlu),fill:pref:grow,3dlu»);
DefaultFormBuilder builder = new DefaultFormBuilder(layout);
builder.setDefaultDialogBorder();
builder.append(«Name», nameField);
builder.nextLine();
builder.nextLine();
builder.append(«Surname», surnameField);
builder.append(searchButton);
builder.nextLine();
builder.nextLine();
builder.append(scrollPane, 5);
this.add(builder.getPanel());
this.setSize(400, 530);
this.setVisible(true);
}
public static void main(String[] args) {
new PlaceboSearchDialog();
}
}
Для построения этого интерфейса я использовал такую полезную вещь как DefaultFormBuilder. Данный builder позволяет отречься от координат и использовать вместо них команды append и nextLine. Помимо этих команд есть nextColumn, nextRow. Выше я использовал CellConstraints для определения место положения компонента. Здесь этот метод только усложнит чтение кода, хотя он и является более гибким, но мы обойдемся и возможностями нашего builder'а. Также из нового здесь добавились параметры такие как «right:pref», «fill:pref:grow», «left:pref:grow».
Данные параметры как вы уже догадались являются составными и могут использоватся как для столбцов так и для строк. Трактуются эти параметры вот так alignment: size: resizeBehavior. Перевод получается как ВЫРАВНИВАНИЕ: РАЗМЕР: ПРОЦЕСС ИЗМЕНЕНИЯ РАЗМЕРА. Например мы в столбец с параметрами left:pref:grow вставили кнопку с названием “Search”, а потом строкой ниже таблицу расширили на все столбцы(builder.append(scrollPane, 5)), так как у столбца стоит параметр «grow», столбец увеличился, но кнопка осталась в нем прежнего размера.
Кстати для проверки моих слов можете заменить строку DefaultFormBuilder builder = new DefaultFormBuilder(layout) на DefaultFormBuilder builder = new DefaultFormBuilder(layout, new FormDebugPanel()). У вас должно получиться в результате вот такое окно:
Красным обведена сетка нашего layout'а, это очень эффективная помощь при отладке интерфейса. В итоге у нас получается очень наглядное представление как будут расположены элементы на экране.
Часто бывает что мы хотим сделать несколько столбцов или строк одного и того же типа. Например нам нужно 5 наборов вот таких столбцов “3dlu,40dlu,3dlu”, для этого чтобы не писать 5 раз один и тот же набор мы можем написать такое выражение
“5*(3dlu,40dlu,3dlu)” вот так просто и красиво.
Теперь коснемся метода builder.append(String label, JComponent component). Данный метод нашего builder'а работает очень хитро, он в первый столбец вставляет JLabel с переданной надписью(пример:builder.append(«Name», nameField) ), потом пропускает один столбец и вставляет уже сам компонент. Такой странный на первый взгляд механизм позволяет очень быстро накидать бизнес формы, а также экономить на ручном создании JLabel'ов.
На этом я заканчиваю статью, следующая будет в понедельник.
Официальный сайт JGoodies