Developer

A calendar control for Swing

Dates are a fundamental aspect of any programming language, but their display can be cumbersome. Learn how to create a Java calendar control using the Swing libraries.


Dates are one of the most fundamental data types, so any language or database provides support for them, either built in or as a class library. Java is no exception; the Java API provides support for representing, computing, comparing, displaying, and parsing dates in a portable, cross-platform and language-independent way. In this article I present a custom control for Swing that allows you to visually pick a date instead of typing it. This way you can avoid invalid dates altogether and offer the user a visual clue as a bonus.

Dates and Java
Java represents dates and times using the class java.util.Date and its subclasses. Despite its name, the Date class has no notion of dates (day, month, year, etc.) in the usual sense. Technically, it is just a point in time, represented as the number of milliseconds elapsed since Jan. 1, 1970, 00:00:00 GMT. Although the class Date has several methods to deal with dates, they were all deprecated.

In order to deal with dates in a portable way, JDK 1.1 introduced the abstract class java.util.Calendar. Concrete subclasses of Calendar convert a point in time into a meaningful date according to a calendar system. This is because different calendar systems employ different rules to compute dates (e.g. Gregorian calendar, Julian calendar, lunar calendar).

The Java API already provides the class java.util.GregorianCalendar to deal with dates according to the Gregorian calendar system, the one in use today.

Finally, the class java.text.DateFormat is an abstraction for formatting and parsing dates in a language-independent manner, following the rules and conventions of a given language/locale. Concrete subclasses of DateFormat performs the actual work. For example, the class java.text.SimpleDateFormat allows you to parse/format a date/time according to a given pattern.

Together, these three base classes (Date, Calendar, and DateFormat) provide a powerful and flexible framework to deal with dates. Although it may look confusing at first, once you understand it you’ll see that this organization makes sense and that there’s a logical reasoning behind it (check the JDK API documentation, which provides more extensive documentation and examples).

Custom date control
Although Java provides everything you need to work with dates, dealing with three different classes is a bit cumbersome—not to mention their API. Sometimes you need to call a lot of methods and employ several objects to carry on a simple task.

Besides that, Swing does not provide a component for entering dates. Of course, it’s not difficult to use a standard control, like a text box, to do that. However, dates are so common in applications that it‘s not unusual to write similar code over and over, across projects, to input, parse, and check dates.

For this reason I created a simple custom control you can use to enter a date. Basically, it’s just a standard button that displays a date (see Figure A).

Figure A
Custom date control


When clicked, a calendar dialog pops up and allows you to select a new date (see Figure B). Clicking on the OK button updates the button's date.

Figure B
Calendar dialog popup


This simplifies the application's logic because the user can't enter an invalid date. And since the dialog looks like a calendar, it’s easy to figure out which day of the week a date corresponds to, which is important in certain applications.

The custom button control is represented by the class DateButton (Listing A). Using it is straightforward—just instantiate a DateButton object and add it to a container, the same way you do with a standard control.

The button's date is represented as a Date object, implemented as a bound property named "date." That means you can set and get it, as well as register a PropertyChangeListener to be notified when the date changes. Table A shows DateButton's API, and Listing B is a simple example that shows how to use it.
Table A
The custom button API is straightforward. You can use one of the constructors to create an instance and get and set the date property. Notice that since it is a standard button, it inherits a lot of methods, including the methods to register listeners.
Method Description
DateButton(Date) Creates a new DateButton initialized with the given date.
DateButton( ) Creates a new DateButton initialized with the system's date.
getDate( ) Gets the value of the date property; that is, the button's date.
setDate(Date) Sets the value of the date property; that is, the button's date.
Custom button control API

The calendar dialog
Besides the custom DateButton control, I also created a custom dialog, CalendarChooser (see Listing C), that allows you to pick a date selecting a month and year from a list, and the day from a calendar (see Figure B). Although it is automatically displayed by the DateButton control, you can also use it on your own. Just create an instance of the CalendarChooser class and call one of its select methods (see Table B for the complete API).
Table B
Using the calendar dialog to select dates is very simple. Just use one of the constructors to create an instance of the dialog and call one of its methods to select a date.
Method Description
DateChooser(Dialog, title) Creates a new DateChooser with the given dialog as the parent and the given title.
DateChooser(Dialog) Creates a new DateChooser with the given dialog as the parent and no title.
DateChooser(Frame, title) Creates a new DateChooser with the given frame as the parent and the given title.
DateChooser(Frame) Creates a new DateChooser with the given frame as the parent and no title.
select(Date) Displays the dialog box with the given date selected and allows you to change it; returns the date selected or null if the cancel button was pressed or the dialog was closed.
select( ) Same as above, but using the system's date as the selected date.
Calendar dialog API

The DateChooser class is a bit complex. I had to create a new control for the monthly calendar since none of the standard controls had the features I wanted. On the other hand, it’s a good example of how easy it is to create a new control, complete with mouse and keyboard interaction.

Notice that the years displayed in the year selection list box are predetermined by the constants FIRST_YEAR and LAST_YEAR. Likewise, other constants determine colors and other visual aspects of the dialog. With some effort, it’s not difficult to change them to properties you can change on the fly.

Also, it’s important to keep in mind that the DateChooser class and DateButton are customized for the English language (months and days of the weeks) and U.S. date format. These are also easy to change since they are all defined through constants. If you need to, it’s also possible to make it totally language independent.

Download the code covered in this article
DateButton.java
Demo.java
DateChooser.java


Put it to good use
Java provides great support for dates. Although it doesn’t provide direct support for entering dates in interactive applications, it’s not difficult to create custom controls that are generic enough to reuse between applications.

Editor's Picks