65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 HTML 模板简化 Swing GUI 创建

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (5投票s)

2010年11月24日

CPOL

2分钟阅读

viewsIcon

57876

展示了如何在 HTML 风格中管理 Swing 组件

引言

在 Java 中创建 GUI 比较困难。普通的代码看起来像

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 个字段... TableLayoutMigLayout 可以简化包含许多字段的布局,但无论如何你仍然需要编写 Java 代码。

背景

很多程序员(尤其是在俄罗斯)都是从 Delphi 开始的。Delphi 的一个很棒之处在于你根本不需要编写 GUI 代码。GUI 标记位于单独的文件中,并通过 IDE 与应用程序链接。

Jetbrains IntelliJ Idea 也使用了几乎相同的方法。标记位于 .form 文件中,并由 IDE 转换为 Java 代码。此外,表单(控制器)的字段会注入相应的组件。

Using the Code

我的方法是将所有标记放入外部文件,并在运行时借助框架构建表单。这种方法类似于 IOC 模式——你无需考虑表单的管理,只需以声明方式描述它并使用结果即可。

所以这里有一个例子

/ru/swing/html/example/LoginForm.html 
<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="https://codeproject.org.cn/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 组件。例如,<body> 将生成 javax.swing.JPanel

'display' 属性告诉将在标签的组件中使用哪个布局管理器。'border' 告诉它将使用 java.awt.BorderLayout

每个直接子标签都放置在父组件中。大多数布局(例如 BorderLayout)使用 'align' 属性作为约束来放置组件。BorderLayout 的默认约束是 center,因此表格将放置在 JPanel 的中心部分。

另外请注意,使用了标签 <table>。它将生成 JPanel,就像 <body> 一样,但会将 TableLayout 设置为布局管理器。之后,它将专门处理其子项,将所有 <td> 内容放置在相应的单元格中。

以类似的方式,<form> 生成带有 MigLayout 布局管理器的 JPanel

现在让我们将此表单绑定到控制器

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);
    }
}

使用以下方式加载并绑定表单的标记

        try {
            Binder.bind(this);
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 

此调用搜索文件 /ru/swing/html/example/LoginForm.html(因为类名为 ru.swing.html.example.LoginForm),加载它,构建 Swing 组件树,然后将其绑定到控制器,因此标签的 id 值等于 @Bind 注释的值的组件将被注入到字段中。

最终结果如下所示

loginform.jpg

链接

历史

  • 2010 年 11 月 24 日:初始发布
© . All rights reserved.