用 Java 创建字体对话框
创建一个 Swing 对话框来选择字体。
引言
作为上学期 Java 编程课的毕业项目,我演示了如何在 Java 应用程序中模仿 Windows 记事本的各项功能。大多数算法都很常规,因为 Java API 非常强大。API 中唯一明显的缺失是缺少一个类似于 JFileChooser
或 JColorChooser
的对话框来选择字体。为了不省略选择字体的功能,我选择自己实现它。
字体对话框的需求很简单
- 对话框必须显示用户系统上所有可用的字体。
- 用户必须能够操作字体的系列、样式和大小。
- 实现必须包括字体预览。
- 实现必须公开一个字体对象供其他地方使用。
使用代码
布局窗体
对话框 GUI 部分的代码包含在 initComponents()
方法中。我使用 BorderLayout
作为窗体的主要布局。中心组件是一个使用 GridLayout
管理器的 JPanel
。GridLayout
本身包含两个 JPanel
- 一个用于用户控件(fontPanel
),一个用于预览(previewPanel
)。用户控件面板使用 GridBagLayout
管理器,预览面板使用 BorderLayout
。主 BorderLayout
的南部组件包含窗体按钮的第三个重要面板(buttonPanel
),它使用 FlowLayout
,组件右对齐。所有代码都可以在代码列表中找到。
initComponents()
方法还做了其他几件事:它声明并初始化了组件,并为每个需要的控件创建了匿名内部监听器类。我在对话框中使用了三个 JList
组件作为用户控件 - 一个用于列出可用的字体系列(lstFont
),一个用于列出可用的样式(lstStyle
),一个用于列出潜在的大小(lstSize
)。它还在创建时将对话框置于用户屏幕中央。
初始化字体系列列表框的代码是 initComponents()
方法中唯一值得注意的代码。
lstFont = new javax.swing.JList(
GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
上面的代码查询系统所有可用的字体,并将它们加载到列表框中,满足了对话框的第一个要求。
处理更改事件
三个 JList
更改事件处理程序都具有通用的结构。每个事件处理程序首先基于列表框的当前状态创建一个新的字体对象。然后,它们将新创建的字体对象分配给一个内部字体变量。最后,预览标签的字体被设置为内部字体变量。这确保了对 getFont()
的任何调用都与对话框向用户显示的同步。这满足了对话框的第二个和第三个要求。
架构
窗体的架构非常简单。我使用了一个私有的字体对象,它通过三个列表框的更改事件进行操作 - 一个用于字体系列,一个用于字体样式,一个用于字体大小(参见图 1)。字体对象会立即反映在预览面板中,并通过公共 getFont()
方法公开。调用应用程序可以使用 getFont()
方法来设置任何对象的字体。这满足了对话框的第四个要求。
构造函数
实现一个用于修改其他控件属性的对话框的常见方法之一是在对话框的构造函数中包含对该控件的引用。通常,在每个构造函数中包含对尽可能通用的超类的引用,以便更多的子类可以使用该对话框。然后,您将使用一个要更改的组件的引用来实例化对话框,并在用户单击“确定”按钮时更改属性。然后对话框将自行销毁。当只有少数几种组件使用该对话框时,这样做是有意义的。对于 JFontChooser
,我决定这样做太费事了。
实现的第二种方法是将对话框与组件解耦,并在用户完成后从对话框中获取属性。这就是我使用的方法。当然,有个要注意的地方是,调用应用程序负责在程序使用完对话框后将其销毁。这似乎是一笔公平的交易,而且创建对话框的应用程序也需要销毁它是有道理的。当然,对话框会被垃圾回收器回收,但在任何程序中,尽早释放未使用的资源都是一个好习惯。
我创建了四个构造函数来处理两种组件的任何组合 - 一个 JFrame
父组件和一个 Font
对象。零参数构造函数存在,以便我将来可以选择将对话框变成 JavaBean。其他构造函数处理了可能的使用场景。当然,最常用的构造函数是接受 JFrame
和 Font
的那个。那个构造函数允许您反映用户正在修改的组件的当前字体。
使用对话框
使用 JFontChooser
非常简单
- 实例化并显示对话框。
- 确定用户是否单击了“确定”按钮。
- 如果选择了“确定”按钮,则更改组件的属性 - 否则,什么也不做。
- 销毁对话框。
使用 JFontChooser
的代码可能看起来像这样
JFontChooser fd = new JFontChooser(this,txtDoc.getFont());
fd.show();
if(fd.getReturnStatus() == fd.RET_OK){
txtDoc.setFont(fd.getFont());
}
fd.dispose();
上面的代码假设调用来自 JFrame
,并且 txtDoc
是一个文本组件,具有相应的 getter 和 setter 方法来获取其内部字体。但是,该对话框不限于文本组件 - 您可以自由地将其用于任何需要 Font
对象作为属性的组件。请注意,只有在单击“确定”按钮时,getReturnStatus()
才会返回 RET_OK
。