Разметка 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