Display a Calendar in a JComboBox import java.awt.*; import java.awt.event.*; import java.util.Calendar; import java.text.SimpleDateFormat; import javax.swing.*; import javax.swing.event.PopupMenuListener; import javax.swing.event.PopupMenuEvent; import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.basic.ComboPopup; import javax.swing.plaf.metal.MetalComboBoxUI; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; import javax.swing.border.EmptyBorder; import com.sun.java.swing.plaf.motif.MotifComboBoxUI; import com.sun.java.swing.plaf.windows.WindowsComboBoxUI; public class DateComboBox extends JComboBox { protected SimpleDateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy"); public void setDateFormat(SimpleDateFormat dateFormat) { this.dateFormat = dateFormat; } public void setSelectedItem(Object item) { // Could put extra logic here or in renderer when item is instanceof Date, Calendar, or String // Dont keep a list ... just the currently selected item removeAllItems(); // hides the popup if visible addItem(item); super.setSelectedItem(item); } public void updateUI() { ComboBoxUI cui = (ComboBoxUI) UIManager.getUI(this); if (cui instanceof MetalComboBoxUI) { cui = new MetalDateComboBoxUI(); } else if (cui instanceof MotifComboBoxUI) { cui = new MotifDateComboBoxUI(); } else if (cui instanceof WindowsComboBoxUI) { cui = new WindowsDateComboBoxUI(); } setUI(cui); } // Inner classes are used purely to keep DateComboBox component in one file ////////////////////////////////////////////////////////////// // UI Inner classes -- one for each supported Look and Feel ////////////////////////////////////////////////////////////// class MetalDateComboBoxUI extends MetalComboBoxUI { protected ComboPopup createPopup() { return new DatePopup( comboBox ); } } class WindowsDateComboBoxUI extends WindowsComboBoxUI { protected ComboPopup createPopup() { return new DatePopup( comboBox ); } } class MotifDateComboBoxUI extends MotifComboBoxUI { protected ComboPopup createPopup() { return new DatePopup( comboBox ); } } ////////////////////////////////////////////////////////////// // DatePopup inner class ////////////////////////////////////////////////////////////// class DatePopup implements ComboPopup, MouseMotionListener, MouseListener, KeyListener, PopupMenuListener { protected JComboBox comboBox; protected Calendar calendar; protected JPopupMenu popup; protected JLabel monthLabel; protected JPanel days = null; protected SimpleDateFormat monthFormat = new SimpleDateFormat("MMM yyyy"); protected Color selectedBackground; protected Color selectedForeground; protected Color background; protected Color foreground; public DatePopup(JComboBox comboBox) { this.comboBox = comboBox; calendar = Calendar.getInstance(); //String[] dts = {dt}; int yr = calendar.get(Calendar.YEAR); int mn = calendar.get(Calendar.MONTH); int dts = calendar.get(Calendar.DATE); String dt = dts+"/"+mn+"/"+yr; comboBox.addItem(dt); // check Look and Feel background = UIManager.getColor("ComboBox.background"); foreground = UIManager.getColor("ComboBox.foreground"); selectedBackground = UIManager.getColor("ComboBox.selectionBackground"); selectedForeground = UIManager.getColor("ComboBox.selectionForeground"); initializePopup(); } //======================================== // begin ComboPopup method implementations // public void show() { try { // if setSelectedItem() was called with a valid date, adjust the calendar calendar.setTime( dateFormat.parse( comboBox.getSelectedItem().toString() ) ); } catch (Exception e) {} updatePopup(); popup.show(comboBox, 0, comboBox.getHeight()); } public void hide() { popup.setVisible(false); } protected JList list = new JList(); public JList getList() { return list; } public MouseListener getMouseListener() { return this; } public MouseMotionListener getMouseMotionListener() { return this; } public KeyListener getKeyListener() { return this; } public boolean isVisible() { return popup.isVisible(); } public void uninstallingUI() { popup.removePopupMenuListener(this); } public void mousePressed( MouseEvent e ) {} public void mouseReleased( MouseEvent e ) {} // something else registered for MousePressed public void mouseClicked(MouseEvent e) { if ( !SwingUtilities.isLeftMouseButton(e) ) return; if ( !comboBox.isEnabled() ) return; if ( comboBox.isEditable() ) { comboBox.getEditor().getEditorComponent().requestFocus(); } else { comboBox.requestFocus(); } togglePopup(); } protected boolean mouseInside = false; public void mouseEntered(MouseEvent e) { mouseInside = true; } public void mouseExited(MouseEvent e) { mouseInside = false; } // MouseMotionListener public void mouseDragged(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} // KeyListener public void keyPressed(KeyEvent e) {} public void keyTyped(KeyEvent e) {} public void keyReleased( KeyEvent e ) { if ( e.getKeyCode() == KeyEvent.VK_SPACE || e.getKeyCode() == KeyEvent.VK_ENTER ) { togglePopup(); } } /** * Variables hideNext and mouseInside are used to * hide the popupMenu by clicking the mouse in the JComboBox */ public void popupMenuCanceled(PopupMenuEvent e) {} protected boolean hideNext = false; public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { hideNext = mouseInside; } public void popupMenuWillBecomeVisible(PopupMenuEvent e) {} protected void togglePopup() { if ( isVisible() || hideNext ) { hide(); } else { show(); } hideNext = false; } // Note *** did not use JButton because Popup closes when pressed protected JLabel createUpdateButton(final int field, final int amount) { final JLabel label = new JLabel(); final Border selectedBorder = new EtchedBorder(); final Border unselectedBorder = new EmptyBorder(selectedBorder.getBorderInsets(new JLabel())); label.setBorder(unselectedBorder); label.setForeground(foreground); label.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent e) { calendar.add(field, amount); updatePopup(); } public void mouseEntered(MouseEvent e) { label.setBorder(selectedBorder); } public void mouseExited(MouseEvent e) { label.setBorder(unselectedBorder); } }); return label; } protected void initializePopup() { JPanel header = new JPanel(); // used Box, but it wasn't Opaque header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS)); header.setBackground(background); header.setOpaque(true); JLabel label; label = createUpdateButton(Calendar.YEAR, -1); label.setText("<<"); label.setToolTipText("Previous Year"); header.add(Box.createHorizontalStrut(12)); header.add(label); header.add(Box.createHorizontalStrut(12)); label = createUpdateButton(Calendar.MONTH, -1); label.setText("<"); label.setToolTipText("Previous Month"); header.add(label); monthLabel = new JLabel("", JLabel.CENTER); monthLabel.setForeground(foreground); header.add(Box.createHorizontalGlue()); header.add(monthLabel); header.add(Box.createHorizontalGlue()); label = createUpdateButton(Calendar.MONTH, 1); label.setText(">"); label.setToolTipText("Next Month"); header.add(label); label = createUpdateButton(Calendar.YEAR, 1); label.setText(">>"); label.setToolTipText("Next Year"); header.add(Box.createHorizontalStrut(12)); header.add(label); header.add(Box.createHorizontalStrut(12)); popup = new JPopupMenu(); popup.setBorder(BorderFactory.createLineBorder(Color.black)); popup.setLayout(new BorderLayout()); popup.setBackground(background); popup.addPopupMenuListener(this); popup.add(BorderLayout.NORTH, header); } // update the Popup when either the month or the year of the calendar has been changed protected void updatePopup() { monthLabel.setText( monthFormat.format(calendar.getTime()) ); if (days != null) { popup.remove(days); } days = new JPanel(new GridLayout(0, 7)); days.setBackground(background); days.setOpaque(true); Calendar setupCalendar = (Calendar) calendar.clone(); setupCalendar.set(Calendar.DAY_OF_WEEK, setupCalendar.getFirstDayOfWeek()); for (int i = 0; i < 7; i++) { int dayInt = setupCalendar.get(Calendar.DAY_OF_WEEK); JLabel label = new JLabel(); label.setHorizontalAlignment(JLabel.CENTER); label.setForeground(foreground); if (dayInt == Calendar.SUNDAY) { label.setText("Sun"); } else if (dayInt == Calendar.MONDAY) { label.setText("Mon"); } else if (dayInt == Calendar.TUESDAY) { label.setText("Tue"); } else if (dayInt == Calendar.WEDNESDAY) { label.setText("Wed"); } else if (dayInt == Calendar.THURSDAY) { label.setText("Thu"); } else if (dayInt == Calendar.FRIDAY) { label.setText("Fri"); } else if (dayInt == Calendar.SATURDAY){ label.setText("Sat"); } days.add(label); setupCalendar.roll(Calendar.DAY_OF_WEEK, true); } setupCalendar = (Calendar) calendar.clone(); setupCalendar.set(Calendar.DAY_OF_MONTH, 1); int first = setupCalendar.get(Calendar.DAY_OF_WEEK); for (int i = 0; i < (first - 1); i++) { days.add(new JLabel("")); } for (int i = 1; i <= setupCalendar.getActualMaximum(Calendar.DAY_OF_MONTH); i++) { final int day = i; final JLabel label = new JLabel(String.valueOf(day)); label.setHorizontalAlignment(JLabel.CENTER); label.setForeground(foreground); label.addMouseListener(new MouseListener() { public void mousePressed(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mouseReleased(MouseEvent e) { label.setOpaque(false); label.setBackground(background); label.setForeground(foreground); calendar.set(Calendar.DAY_OF_MONTH, day); comboBox.setSelectedItem(dateFormat.format(calendar.getTime())); hide(); comboBox.requestFocus(); } public void mouseEntered(MouseEvent e) { label.setOpaque(true); label.setBackground(selectedBackground); label.setForeground(selectedForeground); } public void mouseExited(MouseEvent e) { label.setOpaque(false); label.setBackground(background); label.setForeground(foreground); } }); days.add(label); } popup.add(BorderLayout.CENTER, days); popup.pack(); } } public static void main(String args[]) { JFrame f = new JFrame(); Container c = f.getContentPane(); c.setLayout(new FlowLayout()); c.add(new JLabel("Date:")); DateComboBox dcb = new DateComboBox(); c.add(dcb); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setSize(200, 100); f.show(); } }