DateChooser

Esta classe se propõe a exibir um JDialog com um calendário e opção para escolher dia, mês e ano. Retorna um tipo java.util.Date

DateChooser

import java.awt.Color;

import java.awt.Container;

import java.awt.Dialog;

import java.awt.Frame;

import java.awt.GridLayout;

import java.awt.LayoutManager;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.FocusEvent;

import java.awt.event.FocusListener;

import java.awt.event.ItemEvent;

import java.awt.event.ItemListener;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import java.util.Calendar;

import java.util.Date;

import java.util.GregorianCalendar;

import javax.swing.BorderFactory;

import javax.swing.JButton;

import javax.swing.JComboBox;

import javax.swing.JDialog;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.border.Border;

 

/**

 * Uma caixa de dialogo que tem por objetivo entrada de datas

 * A classe <code>DateChooser</code> apresenta um calendar e permite

 * o usuário selecionar visualmente dia, mês e ano. Não permitindo selecionar

 * uma data inválida.

 **/

public class DateChooser extends JDialog implements ItemListener, MouseListener, FocusListener, KeyListener, ActionListener

{

 /** nome dos meses */

 private static final String[] MONTHS = 

         new String[] {"Janeiro""Fevereiro""Março"   , "Abril"  , "Maio"    , "Junho"   ,

                       "Julho"  , "Agosto"   , "Setembro""Outubro""Novembro""Dezembro"};

 

 /** nomes dos dias da semana */

 private static final String[] DAYS = new String[] {"Dom","Seg","Ter","Qua","Qui","Sex","Sáb"};

 

 /** posição X e Y na tela do dialog, por padrão é na posição zero */

 private int posX = 0;

 private int posY = 0;

 

 /** cor dos dias da semana no cabeçalho */

 private static final Color WEEK_DAYS_FOREGROUND = Color.black;

 

 /** cor dos números */

 private static final Color DAYS_FOREGROUND = Color.blue;

 

 /** cor do dia selecionado */

 private static final Color SELECTED_DAY_FOREGROUND = Color.white;

 

 /** cor do texto do dia selecionado */

 private static final Color SELECTED_DAY_BACKGROUND = Color.blue;

 

 /** Empty border, usado quando o calendário não possui o foco */

 private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(1,1,1,1);

 

 /** Border usado quando calendário tem foco */

 private static final Border FOCUSED_BORDER = BorderFactory.createLineBorder(Color.yellow,1);

 

 /** primeiro ano permitido no calendário */

 private static final int FIRST_YEAR = 1920;

 

 /** último ano permitido */

 private static final int LAST_YEAR = 2020;

 

 /** Variável usada para calcular as datas */

 private GregorianCalendar calendar;

 

 /** Calendar, as a matrix of labels. The first row represents the

        first week of the month, the second row, the second week, and

        so on. Each column represents a day of the week, the first is

        Sunday, and the last is Saturday. The label's text is the

        number of the corresponding day. */

 private JLabel[][] days;

 

 /** Day selection control. It is just a panel that can receive the

        focus. The actual user interaction is driven by the

        <code>DateChooser</code> class. */

 private FocusablePanel daysGrid;

 private JComboBox month;

 private JComboBox year;

 private JButton ok;

 private JButton cancel;

 

 /** Day of the week (0=Sunday) corresponding to the first day of

        the selected month. Used to calculate the position, in the

        calendar ({@link #days}), corresponding to a given day. */

 private int offset;

 

 /** Last day of the selected month. */

 private int lastDay;

 

 /** Selected day. */

 private JLabel day;

 

 /** <code>true</code> if the "Ok" button was clicked to close the

        dialog box, <code>false</code> otherwise. */

 private boolean okClicked;

 

 /**

  * Custom panel that can receive the focus. Used to implement the

  * calendar control.

  **/

 private static class FocusablePanel extends JPanel

 {

         /**

          * Constructs a new <code>FocusablePanel</code> with the given

          * layout manager.

          *

          * @param layout layout manager

          **/

         public FocusablePanel( LayoutManager layout ) {

                 super( layout );

         }

 

         /**

          * Always returns <code>true</code>, since

          * <code>FocusablePanel</code> can receive the focus.

          *

          * @return <code>true</code>

          **/

         public boolean isFocusTraversable() {

                 return true;

         }

 }

 

 /**

  * Initializes this <code>DateChooser</code> object. Creates the

  * controls, registers listeners and initializes the dialog box.

  **/

 private void construct()

 {

         calendar = new GregorianCalendar();

 

         month = new JComboBox(MONTHS);

         month.addItemListener( this );

 

         year = new JComboBox();

         for ( int i=FIRST_YEAR; i<=LAST_YEAR; i++ )

                 year.addItem( Integer.toString(i) );

         year.addItemListener( this );

 

         days = new JLabel[7][7];

         for ( int i=0; i<7; i++ ) {

                 days[0][i] = new JLabel(DAYS[i],JLabel.RIGHT);

                 days[0][i].setForeground( WEEK_DAYS_FOREGROUND );

         }

         for ( int i=1; i<7; i++ )

                 for ( int j=0; j<7; j++ )

                 {

                         days[i][j] = new JLabel(" ",JLabel.RIGHT);

                         days[i][j].setForeground( DAYS_FOREGROUND );

                         days[i][j].setBackground( SELECTED_DAY_BACKGROUND );

                         days[i][j].setBorder( EMPTY_BORDER );

                         days[i][j].addMouseListener( this );

                 }

 

         ok = new JButton("Ok");

         ok.addActionListener( this );

         cancel = new JButton("Cancel");

         cancel.addActionListener( this );

 

         JPanel monthYear = new JPanel();

         monthYear.add( month );

         monthYear.add( year );

 

         daysGrid = new FocusablePanel(new GridLayout(7,7,5,0));

         daysGrid.addFocusListener( this );

         daysGrid.addKeyListener( this );

         for ( int i=0; i<7; i++ )

                 for ( int j=0; j<7; j++ )

                         daysGrid.add( days[i][j] );

         daysGrid.setBackground( Color.white );

         daysGrid.setBorder( BorderFactory.createLoweredBevelBorder() );

         JPanel daysPanel = new JPanel();

         daysPanel.add( daysGrid );

 

         JPanel buttons = new JPanel();

         buttons.add( ok );

         buttons.add( cancel );

 

         Container dialog = getContentPane();

         dialog.add( "North", monthYear );

         dialog.add( "Center", daysPanel );

         dialog.add( "South", buttons );

 

         setLocation(posX, posY);

         pack();

         setResizable( false );

         daysGrid.requestFocus();

 }

 

 /**

  * Gets the selected day, as an <code>int</code>. Parses the text

  * of the selected label in the calendar to get the day.

  *

  * @return the selected day or -1 if there is no day selected

  **/

 private int getSelectedDay()

 {

         if ( day == null )

                 return -1 ;

         try {

                 return Integer.parseInt(day.getText());

         catch ( NumberFormatException e ) {

         }

         return -1;

 }

 

 /**

  * Sets the selected day. The day is specified as the label

  * control, in the calendar, corresponding to the day to select.

  *

  * @param newDay day to select

  **/

 private void setSelected( JLabel newDay )

 {

         if ( day != null ) {

                 day.setForeground( DAYS_FOREGROUND );

                 day.setOpaque( false );

                 day.setBorder( EMPTY_BORDER );

         }

         day = newDay;

         day.setForeground( SELECTED_DAY_FOREGROUND );

         day.setOpaque( true );

         if ( daysGrid.hasFocus() )

                 day.setBorder( FOCUSED_BORDER );

 }

 

 /**

  * Sets the selected day. The day is specified as the number of

  * the day, in the month, to selected. The function compute the

  * corresponding control to select.

  *

  * @param newDay day to select

  **/

 private void setSelected( int newDay )

 {

         setSelected( days[(newDay+offset-1)/7+1][(newDay+offset-1)%7] );

 }

 

 /**

  * Updates the calendar. This function updates the calendar panel

  * to reflect the month and year selected. It keeps the same day

  * of the month that was selected, except if it is beyond the last

  * day of the month. In this case, the last day of the month is

  * selected.

  **/

 private void update()

 {

         int iday = getSelectedDay();

         for ( int i=0; i<7; i++ ) {

                 days[1][i].setText( " " );

                 days[5][i].setText( " " );

                 days[6][i].setText( " " );

         }

         calendar.set( Calendar.DATE, 1 );

         calendar.set( Calendar.MONTH, month.getSelectedIndex()+Calendar.JANUARY );

         calendar.set( Calendar.YEAR, year.getSelectedIndex()+FIRST_YEAR );

 

         offset = calendar.get(Calendar.DAY_OF_WEEK)-Calendar.SUNDAY;

         lastDay = calendar.getActualMaximum(Calendar.DATE);

         for ( int i=0; i<lastDay; i++ )

                 days[(i+offset)/7+1][(i+offset)%7].setText( String.valueOf(i+1) );

         if ( iday != -1 ) {

                 if ( iday > lastDay )

                         iday = lastDay;

                 setSelected( iday );

         }

 }

 

 /**

  * Called when the "Ok" button is pressed. Just sets a flag and

  * hides the dialog box.

  **/

 public void actionPerformed( ActionEvent e ) {

         if ( e.getSource() == ok )

                 okClicked = true;

         setVisible(false);

 }

 

 /**

  * Called when the calendar gains the focus. Just re-sets the

  * selected day so that it is redrawn with the border that

  * indicate focus.

  **/

 public void focusGained( FocusEvent e ) {

         setSelected( day );

 }

 

 /**

  * Called when the calendar loses the focus. Just re-sets the

  * selected day so that it is redrawn without the border that

  * indicate focus.

  **/

 public void focusLost( FocusEvent e ) {

         setSelected( day );

 }

 

 /**

  * Called when a new month or year is selected. Updates the calendar

  * to reflect the selection.

  **/

 public void itemStateChanged( ItemEvent e ) {

         update();

 }

 

 /**

  * Called when a key is pressed and the calendar has the

  * focus. Handles the arrow keys so that the user can select a day

  * using the keyboard.

  **/

 public void keyPressed( KeyEvent e ) {

         int iday = getSelectedDay();

         switch ( e.getKeyCode() ) {

         case KeyEvent.VK_ENTER:

                 ok.doClick();

                 break;

         case KeyEvent.VK_ESCAPE:

                 cancel.doClick();

                 break;

         case KeyEvent.VK_LEFT:

                 if ( iday > 1 )

                         setSelected( iday-1 );

                 break;

         case KeyEvent.VK_RIGHT:

                 if ( iday < lastDay )

                         setSelected( iday+1 );

                 break;

         case KeyEvent.VK_UP:

                 if ( iday > 7 )

                         setSelected( iday-7 );

                 break;

         case KeyEvent.VK_DOWN:

                 if ( iday <= lastDay-7 )

                         setSelected( iday+7 );

                 break;

         }

 }

 

 /**

  * Called when the mouse is clicked on a day in the

  * calendar. Selects the clicked day.

  **/

 public void mouseClicked( MouseEvent e ) {

         JLabel day = (JLabel)e.getSource();

         if ( !day.getText().equals(" ") )

                 setSelected( day );

         daysGrid.requestFocus();

 }

 

 public void keyReleased( KeyEvent e ) {}

 public void keyTyped( KeyEvent e ) {}

 public void mouseEntered( MouseEvent e ) {}

 public void mouseExited( MouseEvent e) {}

 public void mousePressed( MouseEvent e ) {}

 public void mouseReleased( MouseEvent e) {}

 

 /**

  * Constructs a new <code>DateChooser</code> with the given title.

  *

  * @param owner owner dialog

  *

  * @param title dialog title

  **/

 public DateChooser( Dialog owner, String title )

 {

         super( owner, title, true );

         construct();

 }

 

 /**

  * Constructs a new <code>DateChooser</code>.

  *

  * @param owner owner dialog

  **/

 public DateChooser( Dialog owner )

 {

         super( owner, true );

         construct();

 }

 

 /**

  * Constructs a new <code>DateChooser</code> with the given title.

  *

  * @param owner owner frame

  *

  * @param title dialog title

  **/

 public DateChooser( Frame owner, String title )

 {

         super( owner, title, true );

         construct();

 }

 

 public DateChooser( Frame owner, String title, int posX, int posY )

 {

         super( owner, title, true );

         this.posX = posX;

         this.posY = posY;

         construct();

 }

 

 /**

  * Constructs a new <code>DateChooser</code>.

  *

  * @param owner owner frame

  **/

 public DateChooser( Frame owner )

 {

         super( owner, true );

         construct();

 }

 

 /**

  * Selects a date. Displays the dialog box, with a given date as

  * the selected date, and allows the user select a new date.

  *

  * @param date initial date

  *

  * @return the new date selected or <code>null</code> if the user

  * press "Cancel" or closes the dialog box

  **/

 public Date select( Date date )

 {

         if (date == null) date = new Date(); 

         calendar.setTime( date );

         int _day = calendar.get(Calendar.DATE);

         int _month = calendar.get(Calendar.MONTH);

         int _year = calendar.get(Calendar.YEAR);

 

         year.setSelectedIndex( _year-FIRST_YEAR );

         month.setSelectedIndex( _month-Calendar.JANUARY );

         setSelected( _day );

         okClicked = false;

         setVisible(true);

         if ( !okClicked )

                 return null;

         calendar.set( Calendar.DATE, getSelectedDay() );

         calendar.set( Calendar.MONTH, month.getSelectedIndex()+Calendar.JANUARY );

         calendar.set( Calendar.YEAR, year.getSelectedIndex()+FIRST_YEAR );

         return calendar.getTime();

 }

 

 /**

  * Selects new date. Just calls {@link #select(Date)} with the

  * system date as the parameter.

  *

  * @return the same as the function {@link #select(Date)}

  **/

 public Date select()

 {

         return select(new Date());

 }

}

 

Exemplo de uso

import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.text.SimpleDateFormat;

import java.util.Date;

import javax.swing.JButton;

import javax.swing.JFrame;

 

public class Geral extends JFrame {

 

 public Geral() {

 

         setSize(200110);

         setDefaultCloseOperation(EXIT_ON_CLOSE);

         setLayout(new FlowLayout());

 

         JButton b = new JButton("Press me");

         add(b);

         b.addActionListener(new ActionListener() {

                 public void actionPerformed(ActionEvent e) {

                         // --------- aqui inicia o exemplo

                         DateChooser dc = new DateChooser((JFrame)null,"Escolha uma data"00);

                         Date newDate = dc.select();

                         if (newDate != null

                                 System.out.println("Data escolhida: " + new SimpleDateFormat("dd/MM/yy EEE").format(newDate));

                         // --------- aqui termina o exemplo

                         

                 }

         }

         );

         setVisible(true);

 }

 

 public static void main(String[] args) {

         new Geral();

 }        

}

 

Tela

 

Permite o uso do teclado quando o foco está na grade de dias, Enter e Esc.