Разметка swing форм с помощью html
Создание swing форм с помощью кода в JAVA — довольно трудоемкое занятие. Обычно код по созданию и размещению форм выглядит примерно так:
JPanel south = new JPanel(new BorderLayout());
south.add(new JLabel(“login”), BorderLayout.WEST);
south.add(new JTextField(),BorderLayout.CENTER);
rootPanel.add(south, BorderLayout.SOUTH);
В данном примере в панель добавляется надпись и текстовое поле. Теперь представьте, что полей — 15 штук. Для упрощения размещения компонентов были разработаны менеджеры компоновки TableLayout
и
MigLayout
, но даже используя их приходится писать java код.
Давайте сравним это с Delphi (знакомым большинству программистов). В Delphi обычно заботиться о коде разметки не надо вообще. Сама разметка хранится в отдельном файле и линкуется IDE.
Похожий подход используется в Jetbrains IDEA. Разметка хранится в файле .form
и преобразуется в java код самой средой. Также есть возможность присваивать полям формы (класса контроллера) значения созданных на форме компонентов.
Я разрабатываю библиотеку, позволяющую хранить код разметки в отдельном файле и динамически подгружать его.
Рассмотрим пример:
/ru/swing/html/example/LoginForm.html
<head> <style type="text/css"> .red { color: red; } .top { vertical-align: top; } #loginForm { x-miglayout-column-constraints: [right]related[grow,fill]; } body { border: compound (empty 12 12 12 12) (compound (etched) (empty 12 12 12 12)); } </style> </head> <body id="rootPanel" style="display: border; width: 400; height:300; border: empty 12 12 12 12"> <table> <tr> <td rowspan="3" class="top"> <img src="http://www.codeproject.com/img/login_icon.gif" alt=""/> </td> <td width="fill"> <form id="loginForm"> <p>Login:</p> <input id="login" type="text" align="wrap"/> <p>Password:</p> <input id="password" type="password" align="wrap" /> </form> </td> </tr> <tr> <td> <p id="result" class="red"></p> </td> </tr> <tr> <td> <div style="display: box; x-boxlayout-direction: horizontal; border: empty 0 0 0 6"> <glue type="horizontal"/> <input type="button" text="OK" id="ok" icon="/img/accept.png" /> <strut type="horizontal" style="width: 6"/> <input type="button" text="Cancel" id="cancel" icon="/img/cancel.png"/> </div> </td> </tr> </table> </body> </html>
Это html код, описывающий форму. Практически каждый html тег преобразуется в соответствующий swing компонент. Например, преобразуется в
javax.swing.JPanel
.
Значение атрибута display
указывает какой менеджер компоновки следует использовать для компонента. Значение border соответствует java.awt.BorderLayout
.
Каждый компонент дочернего тега размещается в родительском компоненте. Большинство менеджеров компоновки (в том числе и BorderLayout
) размещают дочерний компонент, используя значение атрибута align
дочернего компонента в качестве ограничения (см. LayoutManager.add()
). Значение ограничения по умолчанию для BorderLayout
- это center
, т.о. таблица будет размещена в центре панели.
Также следует обратить внимание на использование тега . Он преобразуется в панель с менеджером компоновки
TableLayout
. После создания он особым образом обрабатывает свои дочерние теги, размещая содержимое тегов в нужных ячейках.
Аналогичным образом тег преобразуется в панель с
MigLayout
в качестве менеджера компоновки.
Теперь свяжем форму с контроллером:
package ru.swing.html.example; import org.jdom.JDOMException; import ru.swing.html.Bind; import ru.swing.html.Binder; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; public class LoginForm { @Bind("login") private JTextField login; @Bind("password") private JPasswordField password; @Bind("ok") private JButton okBtn; @Bind("cancel") private JButton cancelBtn; @Bind("rootPanel") private JPanel rootPanel; @Bind("result") private JLabel result; public LoginForm() { try { Binder.bind(this); } catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } init(); } public void init() { okBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { result.setText("Logging in user "+login.getText()); } }); cancelBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { result.setText("Cancel clicked"); } }); } public JPanel getRootPanel() { return rootPanel; } public static void main(String[] args) throws JDOMException, IOException { LoginForm loginForm = new LoginForm(); JFrame f = new JFrame("Test"); f.setSize(400, 200); f.getContentPane().add(loginForm.getRootPanel()); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); } }
Разметка формы загружается и подключается к контроллеру с помощью данного вызова:
Binder.bind(this);
В момент вызова происходит поиск файла /ru/swing/html/example/LoginForm.html
(так как класс называется ru.swing.html.example.LoginForm
), из файла загружается разметка, преобразуется в дерево swing компонент и присоединяется к контроллеру. Присоединение происходит с помощью аннотации @Bind
: ее значение - это идентификатор компонента.
Итоговый результат:
Ссылки:
Сайт проекта: http://code.google.com/p/swinghtmltemplate/
Документация: http://code.google.com/p/swinghtmltemplate/wiki/Documentation_0_3