Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Create a Font Dialog With Java

0.00/5 (No votes)
3 Apr 2009 3  
Create a Swing dialog for choosing fonts.

screenshot.jpg

Introduction

As the culminating project for last semester’s Java programming class, I demonstrated how to emulate the features found in Windows Notepad in a Java application. Most of the algorithms were routine as the Java API is pretty robust. The one glaring omission in the API is a dialog analogous to the JFileChooser or JColorChooser to choose a font. Rather than omit the ability to choose a font, I chose to implement it myself.

The requirements for the font dialog were straightforward:

  1. The dialog must display all the available fonts on the user’s system.
  2. The user must be able to manipulate the font’s family, style, and size.
  3. The implementation must include a preview of the font.
  4. The implementation must expose a font object for use elsewhere.

Using the code

Layout the form

The code for the GUI aspects of the dialog is contained within the initComponents() method. I used a BorderLayout as the main layout for the form. The center component is a JPanel which uses a GridLayout manager. The GridLayout itself contains two JPanels – one for the user controls (fontPanel) and one for the preview (previewPanel). The user control panel uses the GridBagLayout manager and the preview panel uses a BorderLayout. The south component of the main BorderLayout contains the third significant panel for the buttons on the form (buttonPanel), and it uses a FlowLayout with the components aligned on the right side of the panel. All of the code is available in the code listing.

The initComponents() method also does a number of other things: it declares and initializes the components, and creates anonymous inner listener classes for each of the controls that need them. I used three JList components as the user controls in the dialog – one to list the available font families (lstFont), one to list the available styles (lstStyle), and one to list the potential sizes (lstSize). It also positions the dialog in the middle of the user’s screen upon creation.

The code that initiates the font family list box is the only noteworthy code in the initComponents() method:

lstFont = new javax.swing.JList(
  GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());

The above code queries the system for all of the available fonts, and loads them in the list box, satisfying the first requirement of the dialog.

Handling the change events

The three JList change event handlers all share a common structure. Each event handler first creates a new font object based on the current state of the list boxes. They then assign the newly created font object to an internal font variable. Finally, the font of the preview label is set to the internal font variable. This ensures that any call to getFont() is in synch with what the dialog displays to the user. This satisfies the second and third requirements of the dialog.

The architecture

The architecture for the form is pretty simple. I used a private font object that is manipulated through change events of the three list boxes – one for the font’s family, one for the font’s style, and one for the font’s size (see figure 1). The font object is immediately reflected in the preview panel, and is exposed by a public getFont() method. Calling applications can make use of the getFont() method to set the font of any object. This satisfies the fourth requirement of the dialog.

model.jpg

The constructors

One of the more common ways to implement a dialog that manipulates the properties of some other control is to include a reference to the component in the constructor(s) of the dialog. It’s customary to include references to as generic a superclass as possible in each constructor so that more subclasses can make use of the dialog. You’d then instantiate the dialog with a reference to the component to be changed and change the property when the user clicks the “OK” button. The dialog would then dispose off itself. This makes sense when there are only a couple of different types of components that make use of the dialog. In the case of the JFontChooser, I decided that this was too much work.

A second way to implement the dialog is to de-couple the dialog from the component and get the properties from the dialog after the user is finished with it. That’s the method I used. The caveat, of course, is that the calling application is responsible for disposing the dialog after the program is done with it. This seemed like a fair trade-off, and it makes sense that the application that creates the dialog needs to destroy it as well. Sure, the dialog will be reclaimed by the garbage collector, but it’s a good habit to free unused resources as soon as possible in any program.

I created four constructors to handle any combination of two components – a JFrame parent and a Font object. The zero-argument constructor exists so that I can make the dialog a JavaBean if I choose to later on. The other constructors handle the possible use scenarios. Of course, the most useful constructor is the one which expects both a JFrame and a Font. That’s the one that allows you to reflect the current font of the component you are allowing the user to manipulate.

Using the dialog

Using the JFontChooser is pretty straightforward:

  1. Instantiate and show the dialog.
  2. Determine if the user clicked the “OK” button.
  3. If the “OK” button is selected, change the property of the component – otherwise, do nothing.
  4. Dispose off the dialog.

The code for using the JFontChooser might look something like this:

JFontChooser fd = new JFontChooser(this,txtDoc.getFont());
fd.show();
if(fd.getReturnStatus() == fd.RET_OK){
       txtDoc.setFont(fd.getFont());
}
fd.dispose();

The above assumes that the call is made from a JFrame and that txtDoc is a text component with the corresponding getter and setter methods for its internal font. The dialog is not, however, limited to text components – you’re free to use it with any component that expects a Font object as a property. Note that getReturnStatus() will only return RET_OK if the “OK” button is clicked.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here