Java Swing 日历 控件

这是我改写的网上的DateChooser代码后的作品,使用效果如图所示。用法参考备注,以及Main函数中用法。

Java Swing 日历 控件

 

/**

 * 

 * Copyright: Ares.

 * All Rights Reserved. 

 * Company: Insigma HT/上海创图

 * @author Ares <a href="mailto:[email protected]>send email</a>

 * @date 2013-11-17 16:53

 *

 * Revision History

 *

 * Date            Programmer              Notes

 * ---------    ---------------------  --------------------------------------------

 * 2013-11-17       Ares                    initial

 * 2014-09-16       Ares                    fix bug @n3k123

 * 

 * 1. you can change date format by parameter.

 * 2. you can change week label content by showTEXT.

 * 3. you can change dayOfWeek order by defaultStartDAY.

 */

package com.swing.test;



import java.awt.BasicStroke;

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Component;

import java.awt.Cursor;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.GridLayout;

import java.awt.Point;

import java.awt.Polygon;

import java.awt.Stroke;

import java.awt.Toolkit;

import java.awt.event.FocusEvent;

import java.awt.event.FocusListener;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import java.util.ArrayList;

import java.util.Calendar;

import java.util.Date;

import java.util.List;



import javax.swing.BorderFactory;

import javax.swing.JComponent;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.JTextField;

import javax.swing.PopupFactory;

import javax.swing.SwingUtilities;

import javax.swing.event.AncestorEvent;

import javax.swing.event.AncestorListener;



/**

 * @author Ares

 * @Describe(Date Chooser class)

 */

public class Chooser extends JPanel{



    private static final long serialVersionUID = -5384012731547358720L;

    

    private Calendar calendar;

    private Calendar now = Calendar.getInstance();

    private JPanel calendarPanel;

    private java.awt.Font font = new java.awt.Font("Times",java.awt.Font.PLAIN,12);

    private java.text.SimpleDateFormat sdf;

    private final LabelManager lm = new LabelManager();

    private javax.swing.Popup pop;

    private TitlePanel titlePanel;

    private BodyPanel bodyPanel;

    private FooterPanel footerPanel;

    

    private JComponent showDate;

    private boolean isShow = false;

    private static final String DEFAULTFORMAT = "yyyy-MM-dd";

    private static final String[] showTEXT = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};

    private static WeekLabel[] weekLabels = new WeekLabel[7];

    private static int defaultStartDAY = 0;//0 is from Sun, 1 is from Mon, 2 is from Tue

    private static Color hoverColor = Color.BLUE; // hover color

    



    private Chooser(java.util.Date date, String format, int startDAY){

        if(startDAY > -1 && startDAY < 7) defaultStartDAY = startDAY;

        int dayIndex = defaultStartDAY;

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

            if(dayIndex > 6) dayIndex = 0;

            weekLabels[i] = new WeekLabel(dayIndex, showTEXT[dayIndex]);

            dayIndex ++ ;

        }

        sdf = new java.text.SimpleDateFormat(format);

        calendar = Calendar.getInstance();

        calendar.setTime(date);

        initCalendarPanel();

    }

    

    public static Chooser getInstance(java.util.Date date, String format){

        return new Chooser(date, format, defaultStartDAY);

    }



    public static Chooser getInstance(java.util.Date date){

        return getInstance(date, DEFAULTFORMAT);

    }

    public static Chooser getInstance(String format){

        return getInstance(new java.util.Date(), format);

    }

    public static Chooser getInstance(){

        return getInstance(new java.util.Date(), DEFAULTFORMAT);

    }

    

    private void initCalendarPanel(){

        calendarPanel = new JPanel(new java.awt.BorderLayout());

        calendarPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0xAA, 0xAA, 0xAA)));

        calendarPanel.add(titlePanel = new TitlePanel(), java.awt.BorderLayout.NORTH);

        calendarPanel.add(bodyPanel = new BodyPanel(), java.awt.BorderLayout.CENTER);

        calendarPanel.add(footerPanel = new FooterPanel(),java.awt.BorderLayout.SOUTH);

        this.addAncestorListener(new AncestorListener() {

            public void ancestorAdded(AncestorEvent event) { }

            public void ancestorRemoved(AncestorEvent event) {hidePanel();}

            //hide pop when move component.  

            public void ancestorMoved(AncestorEvent event) {

                hidePanel();

            }

        });

    }

    public void register(final JComponent showComponent) {

        this.showDate = showComponent;

        showComponent.setRequestFocusEnabled(true);

        showComponent.addMouseListener(new MouseAdapter() {

            public void mousePressed(MouseEvent me) {

                showComponent.requestFocusInWindow();

            }

        });

        this.add(showComponent, BorderLayout.CENTER);

        this.setPreferredSize(new Dimension(90, 25));

        this.setBorder(BorderFactory.createLineBorder(Color.GRAY));

        showComponent.addMouseListener(new MouseAdapter() {

            public void mouseEntered(MouseEvent me) {

                if (showComponent.isEnabled()) {

                    showComponent.setCursor(new Cursor(Cursor.HAND_CURSOR));

                }

            }

            public void mouseExited(MouseEvent me) {

                if (showComponent.isEnabled()) {

                    showComponent.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));

                    showComponent.setForeground(Color.BLACK);

                }

            }

            public void mousePressed(MouseEvent me) {

                if (showComponent.isEnabled()) {

                    showComponent.setForeground(hoverColor);

                    if (isShow) {

                        hidePanel();

                    } else {

                        showPanel(showComponent);

                    }

                }

            }

            public void mouseReleased(MouseEvent me) {

                if (showComponent.isEnabled()) {

                    showComponent.setForeground(Color.BLACK);

                }

            }

        });

        showComponent.addFocusListener(new FocusListener() {

            public void focusLost(FocusEvent e) {

                hidePanel();

            }

            public void focusGained(FocusEvent e) { }

        });

    }

    //hide the main panel.

    private void hidePanel() {

        if (pop != null) {

            isShow = false;

            pop.hide();

            pop = null;

        }

    }

 

    //show the main panel.

    private void showPanel(Component owner) {

        if (pop != null) pop.hide();

        Point show = new Point(0, showDate.getHeight());

        SwingUtilities.convertPointToScreen(show, showDate);

        Dimension size = Toolkit.getDefaultToolkit().getScreenSize();

        int x = show.x;

        int y = show.y;

        if (x < 0) x = 0;

        if (x > size.width - 212) x = size.width - 212;

        if (y > size.height - 167) y -= 165;

        pop = PopupFactory.getSharedInstance().getPopup(owner, calendarPanel, x, y);

        pop.show();

        isShow = true;

    }

    // change text or label's content.

    private void commit() {

        if (showDate instanceof JTextField) {

            ((JTextField) showDate).setText(sdf.format(calendar.getTime()));

        }else if (showDate instanceof JLabel) {

            ((JLabel) showDate).setText(sdf.format(calendar.getTime()));

        }

        hidePanel();

    }



    // control panel

    private class TitlePanel extends JPanel {

        

        private static final long serialVersionUID = -2865282186037420798L;

        private JLabel preYear,preMonth,center,nextMonth,nextYear,centercontainer;

        

        public TitlePanel(){

            super(new java.awt.BorderLayout());

            this.setBackground(new java.awt.Color(190, 200, 200));

            initTitlePanel();

        }

        private void initTitlePanel(){

            preYear = new JLabel("<<", JLabel.CENTER);

            preMonth = new JLabel("<", JLabel.CENTER);

            center = new JLabel("", JLabel.CENTER);

            centercontainer = new JLabel("", JLabel.CENTER);

            nextMonth = new JLabel(">", JLabel.CENTER);

            nextYear = new JLabel(">>", JLabel.CENTER);

            

            preYear.setToolTipText("Last Year");

            preMonth.setToolTipText("Last Month");

            nextMonth.setToolTipText("Next Month");

            nextYear.setToolTipText("Next Year");

            

            preYear.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 10, 0, 0));

            preMonth.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 15, 0, 0));

            nextMonth.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 0, 0, 15));

            nextYear.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 0, 0, 10));

            

            centercontainer.setLayout(new java.awt.BorderLayout());

            centercontainer.add(preMonth,java.awt.BorderLayout.WEST);

            centercontainer.add(center,java.awt.BorderLayout.CENTER);

            centercontainer.add(nextMonth,java.awt.BorderLayout.EAST);

            

            this.add(preYear,java.awt.BorderLayout.WEST);

            this.add(centercontainer,java.awt.BorderLayout.CENTER);

            this.add(nextYear,java.awt.BorderLayout.EAST);

            this.setPreferredSize(new java.awt.Dimension(210, 25));

            

            updateDate();

            

            preYear.addMouseListener(new MyMouseAdapter(preYear, Calendar.YEAR, -1));

            preMonth.addMouseListener(new MyMouseAdapter(preMonth, Calendar.MONTH, -1));

            nextMonth.addMouseListener(new MyMouseAdapter(nextMonth, Calendar.MONTH, 1));

            nextYear.addMouseListener(new MyMouseAdapter(nextYear, Calendar.YEAR, 1));

        }

        

        private void updateDate() {

            center.setText(calendar.get(Calendar.YEAR)+"-"+(calendar.get(Calendar.MONTH) + 1));

        }

        // listener for control label.

        class MyMouseAdapter extends java.awt.event.MouseAdapter{

            

            JLabel label;

            private int type, value;

            

            public MyMouseAdapter(final JLabel label, final int type, final int value){

                this.label = label;

                this.type = type;

                this.value = value;

            }

            public void mouseEntered(java.awt.event.MouseEvent me) {

                label.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));

                label.setForeground(hoverColor);

            }

            public void mouseExited(java.awt.event.MouseEvent me) {

                label.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));

                label.setForeground(java.awt.Color.BLACK);

            }

            public void mousePressed(java.awt.event.MouseEvent me) {

                calendar.add(type, value);

                label.setForeground(java.awt.Color.WHITE);

                refresh();

            }

            public void mouseReleased(java.awt.event.MouseEvent me) {

                label.setForeground(java.awt.Color.BLACK);

            }

        }

    }

    // body panel, include week labels and day labels.

    private class BodyPanel extends JPanel {

        

        private static final long serialVersionUID = 5677718768457235447L;

        

        public BodyPanel(){

            super(new GridLayout(7, 7));

            this.setPreferredSize(new java.awt.Dimension(210, 140));

            initMonthPanel();

        }

        private void initMonthPanel(){

            updateDate();

        }

        public void updateDate() {

            this.removeAll();

            lm.clear();

            java.util.Date temp = calendar.getTime();

            Calendar cal = Calendar.getInstance();

            cal.setTime(temp);

            cal.set(Calendar.DAY_OF_MONTH, 1);

            

            int index = cal.get(Calendar.DAY_OF_WEEK);

            // 从当月1号前移,一直移动到面板显示的第一天的前一天;当-index + defaultStartDAY为正数时,为避免面板从当月1号之后开始显示,需要前移一周,确保当月显示完全

            if(index > defaultStartDAY) cal.add(Calendar.DAY_OF_MONTH, -index + defaultStartDAY);

            else cal.add(Calendar.DAY_OF_MONTH, -index + defaultStartDAY - 7);

            

            for (WeekLabel weekLabel : weekLabels) {

                this.add(weekLabel);

            }

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

                cal.add(Calendar.DAY_OF_MONTH, 1);

                lm.addLabel(new DayLabel(cal));

            }

            for (DayLabel my : lm.getLabels()) {

                this.add(my);

            }

        }

    }

    

    private class FooterPanel extends JPanel {

        

        private static final long serialVersionUID = 8135037333899746736L;

        private JLabel dateLabel;

        

        public FooterPanel(){

            super(new BorderLayout());

            initFooterPanel();

        }

        private void initFooterPanel(){

            dateLabel = new JLabel("Today is : "+sdf.format(new java.util.Date()));

            dateLabel.addMouseListener(new MouseListener() {

                

                @Override

                public void mouseReleased(MouseEvent e) {}

                @Override

                public void mousePressed(MouseEvent e) {

                    calendar.setTime(new Date());

                    refresh();

                    commit();

                }

                @Override

                public void mouseExited(MouseEvent e) {

                    dateLabel.setForeground(Color.BLACK);

                }

                @Override

                public void mouseEntered(MouseEvent e) {

                    dateLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));

                    dateLabel.setForeground(hoverColor);

                }

                @Override

                public void mouseClicked(MouseEvent e) {}

            });

            this.add(dateLabel);

        }

        public void updateDate(){};

    }

    //refresh all panel

    private void refresh() {

        titlePanel.updateDate();

        bodyPanel.updateDate();

        footerPanel.updateDate();

        SwingUtilities.updateComponentTreeUI(this);

    }

    

    private class WeekLabel extends JLabel {

        

        private static final long serialVersionUID = -8053965084432740110L;

        private String name;

        

        public WeekLabel(int index, String name){

            super(name, JLabel.CENTER);

            this.name = name;

        }

        public String toString(){

            return name;

        }

    }

    

    private class DayLabel extends JLabel implements java.util.Comparator<DayLabel>, java.awt.event.MouseListener, java.awt.event.MouseMotionListener {



        private static final long serialVersionUID = -6002103678554799020L;

        private boolean isSelected;

        private int year, month, day;

        

        public DayLabel(Calendar cal){

            super(""+cal.get(Calendar.DAY_OF_MONTH), JLabel.CENTER);

            this.year = cal.get(Calendar.YEAR);

            this.month = cal.get(Calendar.MONTH);

            this.day = cal.get(Calendar.DAY_OF_MONTH);

            

            this.setFont(font);

            this.addMouseListener(this);

            this.addMouseMotionListener(this);

            if(month == calendar.get(Calendar.MONTH)) this.setForeground(java.awt.Color.BLACK);

            else this.setForeground(java.awt.Color.LIGHT_GRAY);

            

        }

        public boolean getIsSelected() {

            return isSelected;

        }

        public void setSelected(boolean b, boolean isDrag) {

            isSelected = b;

            if (b && !isDrag) {

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

                calendar.set(year, month, day);

                if (temp == month) {

                    SwingUtilities.updateComponentTreeUI(bodyPanel);

                } else {

                    refresh();

                }

                this.repaint();

            }

        }

        

        @Override

        protected void paintComponent(Graphics g) {

            //set curr select day's background

            if(day == calendar.get(Calendar.DAY_OF_MONTH) && month == calendar.get(Calendar.MONTH)){

                g.setColor(new java.awt.Color(0xBB, 0xBF, 0xDA));

                g.fillRect(0, 0, getWidth(), getHeight());

            }

            //set current day's border

            if(year == now.get(Calendar.YEAR) && month == now.get(Calendar.MONTH) && day == now.get(Calendar.DAY_OF_MONTH)){

                Graphics2D gd = (Graphics2D) g;

                gd.setColor(new java.awt.Color(0x55, 0x55, 0x88));

                Polygon p = new Polygon();

                p.addPoint(0, 0);

                p.addPoint(getWidth() - 1, 0);

                p.addPoint(getWidth() - 1, getHeight() - 1);

                p.addPoint(0, getHeight() - 1);

                gd.drawPolygon(p);

            }

            if (isSelected){

                Stroke s = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 1.0f, new float[] { 2.0f, 2.0f }, 1.0f);

                Graphics2D gd = (Graphics2D) g;

                gd.setStroke(s);

                gd.setColor(Color.BLACK);

                Polygon p = new Polygon();

                p.addPoint(0, 0);

                p.addPoint(getWidth() - 1, 0);

                p.addPoint(getWidth() - 1, getHeight() - 1);

                p.addPoint(0, getHeight() - 1);

                gd.drawPolygon(p);

            }

            super.paintComponent(g);

        }

        public boolean contains(Point p) {

            return this.getBounds().contains(p);

        }

        private void update() {

            repaint();

        }

        @Override

        public void mouseDragged(MouseEvent e) { }

        @Override

        public void mouseMoved(MouseEvent e) { }

        @Override

        public void mouseClicked(MouseEvent e) { }



        @Override

        public void mousePressed(MouseEvent e) {

            isSelected = true;

            update();

        }



        @Override

        public void mouseReleased(MouseEvent e) {

            Point p = SwingUtilities.convertPoint(this, e.getPoint(), bodyPanel);

            this.setForeground(Color.BLACK);

            lm.setSelect(p, false);

            commit();

        }

        @Override // change color when mouse over.

        public void mouseEntered(MouseEvent e) {

            this.setForeground(hoverColor);

            this.repaint();

        }

        @Override // change color when mouse exit.

        public void mouseExited(MouseEvent e) {

            if(month == calendar.get(Calendar.MONTH)) this.setForeground(java.awt.Color.BLACK);

            else this.setForeground(java.awt.Color.LIGHT_GRAY);

            this.repaint();

        }

        @Override

        public int compare(DayLabel o1, DayLabel o2) {

            Calendar c1 = Calendar.getInstance();

            c1.set(o1.year, o1.month, o1.day);

            Calendar c2 = Calendar.getInstance();

            c2.set(o2.year, o2.month, o2.day);

            return c1.compareTo(c2);

        }

        

    }

    

    private class LabelManager {

        private List<DayLabel> list;

        

        public LabelManager(){

            list = new ArrayList<Chooser.DayLabel>();

        }

        

        public List<DayLabel> getLabels(){

            return list;

        }

        public void addLabel(DayLabel label){

            list.add(label);

        }

        public void clear() {

            list.clear();

        }

        public void setSelect(Point p, boolean b) {

            //如果是拖动,则要优化一下,以提高效率  

            if (b) {

                //表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和  

                //将要显示的标签找到了就可以了  

                boolean findPrevious = false, findNext = false;

                for (DayLabel lab : list) {

                    if (lab.contains(p)) {

                        findNext = true;

                        if (lab.getIsSelected()) findPrevious = true;

                        else lab.setSelected(true, b);

                    } else if (lab.getIsSelected()) {

                        findPrevious = true;

                        lab.setSelected(false, b);

                    }

                    if (findPrevious && findNext) return;

                }

            }else {

                DayLabel temp = null;

                for (DayLabel m : list) {

                    if (m.contains(p)) {

                        temp = m;

                    } else if (m.getIsSelected()) {

                        m.setSelected(false, b);

                    }

                }

                if (temp != null) temp.setSelected(true, b);

            }

        }

    }

    

    

    /**

     * @param args

     */

    public static void main(String[] args) {

        JFrame jf = new JFrame("Date Picker Test");

        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jf.setLayout(null);

        jf.setBounds(400, 200, 600, 400);

        

        Chooser ser = Chooser.getInstance();

        javax.swing.JTextField text = new JTextField();

        text.setBounds(10, 10, 200, 30);

        text.setText("2013-10-11");

        ser.register(text);

        

        Chooser ser2 = Chooser.getInstance("yyyy年MM月dd日");

        JLabel label = new JLabel("please click me.");

        label.setBounds(10, 50, 200, 30);

        ser2.register(label);

        

        jf.add(text);

        jf.add(label);

        jf.setVisible(true);

    }

}

 

 

 

 

 

 

你可能感兴趣的:(java swing)