Swing 是一个极其强大的 GUI 工具集。但糟糕的是,有时候其复杂性会影响开发人员挥发它的能力。如果您刚接触 Swing,会觉得像是在学习开波音 747,而您实际上只需要开单引擎的 Cessna 或滑翔机。
Groovy 的?SwingBuilder
?并不能降低各种任务内在的复杂性,比如选择适当的?LayoutManager
?或处理线程问题。它降低的是语法复杂性。Groovy 的命名参数/变量参数构造器非常适合需要实例化的各种?JComponent
,然后马上可以为它们配置一系列设置器。(关于SwingBuilder
?的更多信息,请参见?参考资料)。
但是,同样有价值的是 Groovy 对闭包的使用。对于 Swing,我长期关注的问题是自然的层次结构似乎在实现细节中消失了。在 Java 代码中,会得到一组相互脱节的组件,看不出哪个组件属于哪个组件。可以以任意次序声明?JFrame
、JPanel
?和?JLabel
。在代码中,它们看起来是平等的;但是,实际上?JFrame
?包含?JPanel
,JPanel
?进而包含?JLabel
。清单 8 给出一个示例:
清单 8. HelloJavaSwing.java
import javax.swing.*;
public class HelloJavaSwing {
public static void main(String[] args) {
JPanel panel = new JPanel();
JLabel label = new JLabel("Hello Java Swing");
JFrame frame = new JFrame("Hello Java Swing");
panel.add(label);
frame.add(panel);
frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,300);
frame.setVisible(true);
}
}
|
编译这段代码 (javac HelloJavaSwing.java
) 并运行它 (java HelloJava
),应该会显示图 1 所示的应用程序:
图 1.?HelloJavaSwing
?

?
清单 9 给出用 Groovy 编写的同一个应用程序。可以看到?SwingBuilder
?使用了闭包,这让我们可以清晰地看出拥有关系链。
清单 9. HelloGroovySwing.groovy
import groovy.swing.SwingBuilder
import javax.swing.*
def swingBuilder = new SwingBuilder()
swingBuilder.frame(title:"Hello Groovy Swing",defaultCloSEOperation:JFrame.EXIT_ON_CLOSE,size:[200,300],show:true) {
panel(){
label("Hello Groovy Swing")
}
}
输入?groovy HelloGroovySwing
?会看到图 2 所示的应用程序:
图 2.?HelloGroovySwing
?

?
注意,在?清单 9?中,所有组件名去掉了开头的?J
,方法名中也去掉了多余的?get
?和?set
。接下来,注意?frame
?的命名参数构造器。在幕后,Groovy 调用无参数构造器,然后调用设置器方法,这与前面的 Java 示例没有区别。但是,设置器方法都集中在构造器中,代码更简洁了,去掉?set
?前缀和末尾的圆括号也大大减少了视觉干扰。
如果您不了解 Swing,这段代码看起来可能仍然比较复杂。但是,如果您具备哪怕最粗浅的 Swing 经验,就可以看出它具有 Swing 的特征:干净、清晰和高效。
正如在前一节中所做的,通过脚本了解概念,然后把脚本转换为类。创建文件 Gwitter.groovy,见清单 10。这是 Groovy + Twitter 客户机 UI 的起点。
清单 10. Gwitter UI 的骨架
import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.*
class Gwitter{
static void main(String[] args){
def gwitter = new Gwitter()
gwitter.show()
}
void show(){
def swingBuilder = new SwingBuilder()
swingBuilder.frame(title:"Gwitter",size:[400,500],show:true) {
}
}
}
输入?groovy Gwitter
,确认会出现空的框架。如果一切正常,下一步是在应用程序中添加一个简单的菜单。