5.3 Swing

Swing组件库中的核心类是JComponent。Swing中所有的非顶层窗口的组件类都继承自JComponent类,而顶层窗口组件则继承自AWT中的对应组件。Swing中组件的类名都以“J”作为前缀,以区别于AWT中同样功能的组件。相对于AWT来说,Swing组件库的内容更加丰富,性能也更好。

5.3.1 重要组件类

Swing中的顶层窗口组件需要继承自AWT中的相关组件以支持与底层操作系统的交互。Swing中共有4种顶层窗口组件,分别是javax.swing包中的JFrame、JWindow、JDialog和JApplet。前面提到过,这些顶层窗口组件实际上是为Swing的用户界面提供绘制的区域,这个绘制区域本身又是用javax.swing.JRootPane类的对象来表示的。每个顶层窗口组件都只有唯一的一个直接子组件,是一个JRootPane类的对象。对窗口中内容的操作也在这个JRootPane类的对象上进行。一个JRootPane类的对象所表示的组件由两个部分组成。第一部分是作为内容区域之上的遮罩的一个组件(glass pane)。这个组件覆盖在其他组件之上,大小与当前JRootPane组件一样,可以用来拦截鼠标和键盘事件。在默认情况下,这个组件是不可见的。第二部分是一个javax.swing.JLayeredPane类的对象。在这个JLayeredPane组件中又包含了两个部分:第一部分是作为菜单的javax.swing.JMenuBar类的对象。菜单不是必须存在的。第二部分是作为内容区域的Container类的对象。内容区域是必须存在的。对于一个JRootPane组件来说,最重要的是其中包含的内容区域。内容区域中应该包含一个用户界面中所有非菜单的组件。当通过一个顶层窗口组件的add方法来添加组件的时候,默认这个组件实际上被添加到了内容区域中。同样,在设置一个顶层窗口组件的布局格式的时候,实际上设置的是内容区域的布局格式。顶层窗口组件类都实现了javax.swing.RootPaneContainer接口。通过RootPaneContainer接口中的方法可以对JRootPane组件进行操作,如调用getContentPane方法可以获取内容区域组件,并对这个组件进行操作。

JRootPane的遮罩组件可以用来拦截顶层窗口组件中包含内容区域的JLayeredPane组件上的鼠标和键盘事件,也可以绘制其他内容来盖住JLayeredPane中的组件。当需要暂时屏蔽用户对内容区域的操作时,可以使用这个遮罩组件。JRootPane的遮罩组件可以是任何继承自JComponent类的组件。比如,当程序启动的时候,某些组件可能还没有完全初始化,这时可以把遮罩组件显示出来,给出相关的提示并屏蔽用户的使用。代码清单5-3给出了一个示例。LoadingPane类是一个普通的JComponent的子类,它在界面的正中显示字符,同时捕获所有的鼠标事件但不做任何处理。

代码清单5-3 作为遮罩组件的JComponent的子类


public class LoadingPane extends JComponent{

public LoadingPane(){

addMouseListener(new MouseAdapter(){});

}

public void paintComponent(Graphics g){

g.drawString("加载中……",getWidth()/2,getHeight()/2);

}

}


下一步是把LoadingPane类的对象作为遮罩组件添加到某个JRootPane组件上。代码清单5-4给出了示例的做法。其中关键的是要把遮罩组件设置为可见,使它可以发挥作用。程序运行起来之后,会发现内容区域上的组件都无法接收到鼠标事件,因为这些事件已经被LoadingPane拦截并处理了。

代码清单5-4 把遮罩组件添加到JRootPane组件


LoadingPane pane=new LoadingPane();

frame.setGlassPane(pane);

pane.setVisible(true)


代码清单5-3中的LoadingPane类只是一个简单的遮罩组件的实现。可以根据需要开发出更加复杂的实现,比如只拦截某些组件上的事件,或者实现复杂的图形绘制功能。