8.2 JFrame类
JFrame类是使用JRootPane并且实现了RootPaneContainer接口的Swing高层容器。另外,他使用WindowConstants接口来帮助管理相关操作。
8.2.1 创建JFrame
JFrame类提供了两个基本构造函数:一个用于不带标题的框架,而另一个用来创建带标题的框架。还有另外两个构造函数使用特定的GraphicsConfiguration来创建框架。
public JFrame() JFrame frame = new JFrame(); public JFrame(String title) JFrame frame = new JFrame("Title Bar"); public JFrame(GraphicsConfiguration config) GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gsd[] = ge.getScreenDevices(); GraphicsConfiguration gc[] = gsd[0].getConfigurations(); JFrame frame = new JFrame(gc[0]); public JFrame(String title, GraphicsConfiguration config) GraphicsConfiguration gc = ...; JFrame frame = new JFrame("Title Bar", gc);
8.2.2 JFrame属性
表8-5显示了JFrame的九个属性。
JFrame属性
属性名 | 数据类型 | 访问性 |
accessibleContext | AccessibleContext | 只读 |
contentPane | Container | 读写 |
defaultCloseOperation | int | 读写 |
glassPane | Component | 读写 |
iconImage | Image | 只写 |
jMenuBar | JMenuBar | 读写 |
layeredPane | JLayeredPane | 读写 |
layout | LayoutManager | 只写 |
rootPane | JRootPane | 只读 |
尽管大多数的属性都是实现RootPaneContainer接口的结果,但是有两个特殊的属性:defaultCloseOperation以及layout。(我们首先在第2章看到了defaultCloseOperation。)默认情况下,当用户关闭容器时,JFrame会隐藏自己。要修改这种设置,当设置默认关闭行为时我们可以表8-6中所列表出的常量来作为参数。第一个直接来自于JFrame;其他的则是WindowConstants接口的一部分。
aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
关闭操作常量
常量 | 描述 |
EXIT_ON_CLOSE | 调用System.exit(0) |
DISPOSE_ON_CLOSE | 在窗体上调用dispose() |
ON_NOTHING_ON_CLOSE | 忽略请求 |
HIDE_ON_CLOSE | 在窗体上调用setVisible(false);这是默认行为 |
layout属性是比较奇特的。默认情况下,设置JFrame的布局管理器会将调用传递给内容面板。我们不可以修改JFrame的默认布局管理器。
JFrame还有另外一个静态属性:defaultLookAndFeelDecorated。这个属性与JRootPane的windowDecorationStyle属性结合使用。当设置为true时,新创建的窗体会使用观感中的装饰而不是窗口管理中的装饰进行装饰。当然,只有当前的观感支持窗口装饰时才会发生这种情况。列表8-2显示了另一种创建与图8-2相同的屏幕的方法(通过使用Metal观感所提供的窗口装饰)。
package swingstudy.ch08; import java.awt.EventQueue; import javax.swing.JFrame; public class AdornSample2 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Runnable runner = new Runnable() { public void run() { JFrame.setDefaultLookAndFeelDecorated(true); JFrame frame = new JFrame("Adornment Sample"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300,200); frame.setVisible(true); } }; EventQueue.invokeLater(runner); } }
8.2.3 向JFrame添加组件
因为JFrame实现了RootPaneContainer接口并且使用JRootPane,我们不能直接向JFrame添加组件。相反,我们将组件添加到JFrame所包含的JRootPane。在J2SE 5.0之前,我们需要使用下面的方法来添加组件:
JRootPane rootPane = aJFrame.getRootPane(); Container contentPane = rootPane.getContentPane(); contentPane.add(...);
这可以用下面的语句进行简化:
aJFrame.getContentPane().add(...);
如果我们尝试直接向JFrame添加组件,则会抛出运行时错误。
由于许多建议(或是抱怨?),Sun最终决定将add()方法修改为代理:
aJFrame.add(...);
使用J2SE 5.0时,当我们向JFrame添加组件时,他们实际上被添加到了RootPaneContainer的内容面板。
8.2.4 处理JFrame事件
JFrame类支持11种不同的监听器的注册:
- ComponentListener:确定窗体何时移动或修改尺寸
- ContainerListener:通常并不添加到JFrame,因为我们将组件添加到其JRootPane的内容面板。
- FocusListener:确定窗体何时获得或是失去输入焦点。
- HierarchyBoundsListener:确定窗体何时移动或是修改尺寸。其作用与ComponentListener类似,因为窗体是组件的顶层容器。
- HierarchyListener:确定窗体何时显示或隐藏。
- InputMethodListener:用于国际化时与输入法结合使用。
- KeyListener:通常并不添加到JFrame。相反,我们为其内容面板注册一个键盘动作,如下所示:
JPanel content = (JPanel)frame.getContentPane();
- MouseListener与MouseMotionListener:用于监听鼠标以及鼠标动作事件。
- PropertyChangeListener:用来监听绑定属性的改变。
- WindowListener:来确定窗口何时被图标化或是取消图标化或是用户正在尝试打开或关闭窗口。
通过defaultCloseOperation属性,我们通常并不需要添加WindowListener来帮助处理关闭窗体或是停止程序。
8.2.5 扩展JFrame
如果我们需要扩展JFrame,这个类有两个重要的protected方法:
protected void frameInit()protected JRootPane createRootPane()
通过在子类中重写这些方法,我们可以自定义初始外观以及窗体或是其JRootPane的行为。例如,在列表8-3中所示的ExitableJFrame类的例子中,默认的关闭操作被初始化EXIT_ON_CLOSE状态。无需要为每一个创建的窗体调用setDefaultCloseOperation()方法,我们可以使用这个类进行替换。因为JFrame被继承,我们并不需要在其构造函数中添加frameInit()方法的调用。其父类自动调用这个方法。
package swingstudy.ch08; import javax.swing.JFrame; public class ExitableFrame extends JFrame { public ExitableFrame() { } public ExitableFrame(String title) { super(title); } protected void frameInit() { super.frameInit(); setDefaultCloseOperation(EXIT_ON_CLOSE); } }
注意:如果我们重写JFrame的frameInit()方法,记住首先调用super.frameInit()来初始化其默认行为。如果我们忘记了并没有自己重新实现所有的默认行为,我们的新窗体的外观与行为就会不同。