A JMonth component represents one month from the calendar in an intuitive way. Users can navigate the component using the mouse or the keyboard. The month in view can be selected from the popup that appears when the name of the currently displayed month is clicked.
Here are the main features:
Easy selection of dates
Customization of colors and font
Customization of calendar dates painting using a date renderer
Grid customization
Easy keyboard navigation
API control over the currently displayed month
To understand completely a JMonth component, you might also want to look at JDateComponent.
This section uses the application shown below to explore all these capabilities.
Try this:
Run MonthDemo using Java Web Start or consult the source code for yourself.
Click one of the fonts to change the font used by the component.
Click on the Foreground color button and select a color. The dates of the month are now painted with this color.
Click one a date from the component to select it. The default renderer displays it using an oval. Now, click on the date renderer combo box and select Custom. The new renderer displays selected dates using a rectangle.
Press the "Selection Model" combo box and choose "No Weekends". This will change the selection model used by the component. With the new model, the weekends are not selectable and are marked with a red X.
Click on the "Selection Type" combo box to change the way you can select dates from the component. By choosing Single, you can select only one date at a time. Single Interval allows you to select an interval of dates by dragging the mouse. Multiple Interval allows you to select multiple dates.
To show/hide vertical or horizontal lines click on "Show Vertical Lines" and "Show Horizontal Lines" check boxes. Press the color button to set a color for them.
Click on "Show Week Names" and "Show Week Numbers" to show/hide week numbers and week names.
Click the "Locale" combo box and change the language to German. The name of the month and week days are changed accordingly.
Click the component and press HOME to select the first day of month, then press END to select the last day of month. See below for all the available keyboard shortcuts.
Check the "Toggled Date Selection" box and make sure the "Multiple Interval" selection type is selected. Clicking on several dates from the component will select/unselect them. Now uncheck the "Toggled Date Selection" box. Clicking on several dates from the component will keep selected only the last clicked date.
Because JMonth is in fact a JDateComponent, you can use the setSelectedDate method to select a single date. But there are situations when you might want to select a set of dates. For that, this component has a setSelectedDates method that allows the selection of more than one date.
The following lines of code show how you can select a set of dates in a JMonth component:
Date[] dates = ...this is your array of dates month.setSelectedDates(dates);
This setSelectedDates method is just a convenient way of selecting more dates instead of using the underlying date selection model. For other operations like adding another date to the set of selected dates from a JMonth component you would have to use the date selection model.
The following example shows how you can add another date to the set of selected dates:
Date date = ...this is your date month.getDateSelectionModel().addDateSelectionInterval(date, date);
Whenever working with dates, users might need to select more that just one date. Perhaps they need to select a whole range of dates. To suit these needs, a JMonth component can be configured for a specific type of selection. There are three such types:
single date selection allows the selection of only one date at a time
single interval date selection allows the selection of only one range of dates
multiple interval date selection allows the selection of multiple date ranges
Use setSelectionMode and getSelectionMode methods in order to specify and determine the selection mode that is used. The following lines of code show how you can set each of these types:
//changes the selection mode to accept a single selected date month.setSelectionMode(SelectionMode.SINGLE); //changes the selection mode to accept a single interval of selected dates month.setSelectionMode(SelectionMode.SINGLE_INTERVAL); //changes the selection mode to accept multiple intervals of selected dates month.setSelectionMode(SelectionMode.MULTIPLE_INTERVAL);
To select a range of dates, click on the first date of the interval and then you can either drag the mouse to the last date or press SHIFT and click on the last date.
To select multiple dates, press CTRL and click a date to add it to the set of selected dates.
One important feature of the JMonth is that you can localize it for various languages and regions. The names of the week days, the first day of week, the names of the months are determined on locale basis. By default, the system's locale is used but it can be configured to use any locale.
To change the locale, use the setLocale method. The following line of code changes the locale to Spanish:
month.setLocale(new Locale("es", "ES"));The calendar is configured by default with a specific font and with a set of colors specific to the used look and feel. So, on different look and feels it will use a different set of colors. If you are not satisfied how it looks, you can change the colors to suit your needs. Here is how you can do it.
The following lines of code customize the font and colors of a JMonth component:
month.setForeground(Color.black);
month.setTitleBackground(new Color(50, 100, 255));
month.setTitleForeground(Color.white);
month.setTrailingForeground(Color.gray);
month.setMonthBackground(new Color(255, 255, 100));
month.setFont(new Font("Arial", Font.PLAIN, 13));The JMonth components use a date renderer to paint the dates from the calendar. There would be no need for such a mechanism if all the dates from the calendar would be the same but they are not.
By default, we have the dates of the currently displayed month, trailing dates, restricted dates, selected dates and even a today date which must differentiate one from another in some way. And the only way is to paint them differently. Somebody might decide that they need to have special dates (company dates, holidays, etc) that must be painted differently from all the others and this rendering mechanism is a very flexible solution for such a problem.
A date renderer is similar to other Swing renderers and is an instance of a class that implements the DateRenderer interface. The com.standbysoft.component.date.swing package provides a DefaultDateRenderer that is the renderer used by default in all JMonth components.
The DefaultDateRenderer paints the selected dates as ovals using the title foreground and background colors. The other dates are painted using the other colors specified for JMonth.
The DefaultDateRenderer displays the selected dates as ovals and marks the today date with a red border. Here, we create a custom renderer based on the default one to display the selected dates as rectangles. The following line of code registers an instance of CustomDateRenderer as a date renderer for the JMonth component:
month.setDateRenderer(new CustomDateRenderer());
Here's the implementation for CustomDateRenderer:
/**
* Custom date renderer that extends the default one to display the selected
* dates as rectangles and not like ovals and paints disabled dates with gray
* instead of red.
*/
public class CustomDateRenderer extends DefaultDateRenderer {
/**
* Paints a selected date as a rectangle.
*/
protected void paintSelected(Graphics g) {
g.setColor(month.getTitleBackground());
g.fillRect(1, 1, getWidth() - 1, getHeight() - 1);
}
/**
* Paints the today date as a rectangle with a red border.
*/
protected void paintToday(Graphics g) {
g.setColor(Color.red);
g.drawRect(1, 1, getWidth() - 2, getHeight() - 2);
}
/**
* Paints disabled dates using a gray X.
*/
protected void paintDisabled(Graphics g) {
g.setColor(Color.GRAY);
g.drawLine(3, 3, getWidth() - 3, getHeight() - 3);
g.drawLine(getWidth() - 3, 3, 3, getHeight() - 3);
}
}The JMonth component has a grid that can be used to emphasize the dates from the calendar. You can control the visibility of the vertical and/or horizontal grid lines. The color of the grid can also be customized. By default, the grid is not displayed and the following lines of code show how it can be activated:
month.setGridColor(Color.blue); month.setHorizontalLinesVisible(true); month.setVerticalLinesVisible(true);
The dates of a month are displayed on a 6x7 grid leaving a lot of date positions open. Usually, these positions are filled with trailing dates from the previous or the next month. By default, these dates are enabled but you can disabled them.
You can enable or disable trailing dates using the setTrailingPreviousEnabled and setTrailingNextEnabled methods. The following lines of code hide the trailing dates of a month:
month.setTrailingPreviousEnabled(false); month.setTrailingNextEnabled(false);
The week numbers just give more contextual information about the selected dates. They do not have some special functionality. By default, the week numbers are visible. You can show or hide them using the setWeekNumbersVisible method. The following line of code hides the week numbers:
month.setWeekNumbersVisible(false);
By week names we mean the names of the days of week (Monday, Tuesday, etc). Although it is unlikely that you will want to deactivate week names alone, this feature is useful when you want to deactivate both week names and week numbers. The following lines of code hide both week names and numbers:
month.setWeekNamesVisible(false); month.setWeekNumbersVisible(false);
As we have said above, if you want to select multiple dates, just use the multiple interval selection mode and then CTRL click the dates you want to select. But as you do this, you may find it irritating to hold down the CTRL key. Sometimes, it is more intuitive to use simple mouse clicks to select or unselect the dates that you need.
To solve this problem, a JMonth component has the toggleDateSelectionEnabled property that specifies how it should behave when a date is clicked. When this property is enabled, clicked dates just toggle their state from selected to unselected and conversely. But if it is disabled, clicking on a date means that only that date is selected.
By default, this property is disabled. The following line of code shows how to enable it:
month.setToggleDateSelectionEnabled(true);
One important feature of a month component is its keyboard interface. Users can use the keyboard shortcuts presented in the table below to quickly select a date.
Table 2.1. Keyboard Interface
| Key | Description |
|---|---|
| LEFT ARROW | Select the previous day |
| RIGHT ARROW | Select the next day |
| UP ARROW | Select the same day of week in the previous week |
| DOWN ARROW | Select the same day of week in the next week |
| PAGE UP | Scrolls the display to past months |
| PAGE DOWN | Scrolls the display to future months |
| CTRL + PAGE UP | Scrolls the display to the previous year |
| CTRL + PAGE DOWN | Scrolls the display to the next year |
| HOME | Select the first day in month |
| END | Select the last day in month |
| DELETE | Select none |
| BACKSPACE | Select none |
When one tries to select a date with the keyboard and that date is disabled (cannot be selected) then an adjacent date will be selected. This rule applies to the following keys: LEFT, RIGHT, PAGE UP, PAGE DOWN, CTRL + PAGE UP, CTRL + PAGE DOWN.
For instance if the current date is April 23, 2003 and I want to select May 23, 2003 (PAGE DOWN) but it is disabled then the next date after May 23, 2003 that is not disabled will be selected (perhaps May 24, 2003).
The rule does not apply for UP and DOWN keys because it is not so intuitive. If the same day of week in the previous week is not selectable then it will try to go back until it finds the first week that has the same day of week selectable.