Swing 自定义日期控件

/**
 *
 * Copyright: Ares.
 * All Rights Reserved.
 * Company: Insigma HT/上海创图
 *
 * 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,
                                  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 list;

        public LabelManager(){
            list = new ArrayList();
        }

        public List 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);
    }
}
时间: 2024-08-05 03:40:30

Swing 自定义日期控件的相关文章

安卓自定义日期控件(仿QQ,IOS7)

还记得上篇:高大上的安卓日期时间选择器,本篇是根据上篇修改而来,先看下qq中日期选择的效果: 鉴于目前还没有相似的开源日期控件,因此本人花费了一些时间修改了下之前的日期控件,效果如图: 虽说相似度不是百分之百,但相对其它日期控件是不是更加高大上了许多,哈哈~代码就不在往上贴了,如果感觉不错可以下载源码,并修改成更加符合你的效果. 源码地址:http://download.csdn.net/detail/baiyuliang2013/8692313

安卓自定义日期控件(仿QQ,IOS7)续

本篇是在原来的基础上修改了界面效果,使其更加接近ios7,qq等日期选择控件,看图: 源码地址:http://download.csdn.net/detail/baiyuliang2013/8760159

Java Swing日期控件的使用

1.创建一个日期工具类 package com.zjl.utils; 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; i

WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 日历控件Calendar自定义样式: 日期控件DatePicker自定义样式,及Label标签.水印.清除日期功能扩展: 二.Calendar自定义样式 先看看效果: 从上面图可以看出,日历的显示其实有三种状态,如下面的分解图: "日"部分的显示: "月"部分的显示: &qu

自定义datetimepicker日期控件

Bootstrap v3.3.5 css /* ======================================== ys-datetimepicker ======================================== */ .ys-datetimepicker{     position:relative;     width:100%;     height:32px;     cursor:pointer; } .ys-datetimepicker>input.

My97DatePicker日期控件实现按日、周、月、季、年选择时间段

 http://www.cnblogs.com/kevin-zlg/p/4631413.html 前台页面需要使用日期控件时,同事选择了My97DatePicker,功能还是挺强大的,在使用过程中需要实现按日.按周.按月.按季度.按年选择时间的功能. 控件自身提供了按日.按月和按年选择的功能,但是选择周和选择季度没有,鉴于方便,在选择周时就使用了选择日的状态,选择了日后再计算这一天所属的周的起始和结束日期. 在选择季度时,使用了选择月份的状态,选择月份后计算所属的季度的开始和结束日期. 控件本身

js 常用日期控件使用

一.My97DatePicker 当前最新版本: 4.8 官网:http://www.my97.net/ csdn下载地址: http://download.csdn.net/detail/czw2010/8585183 1. 使用说明: My97DatePicker目录是一个整体,不可破坏里面的目录结构,也不可对里面的文件改名,可以改目录名 My97DatePicker.htm是必须文件,不可删除(4.8以后不存在此文件) 各目录及文件的用途: WdatePicker.js 配置文件,在调用的

jsp日期插件My97DatePicker 强大的日期控件 使用方便简单

本文属转载(希望对编程爱好者有所帮助)详情请访问官方网站 http://www.my97.net/dp/index.asp 一. 简介 1. 简介 目前的版本是:4.7 2. 注意事项 My97DatePicker目录是一个整体,不可破坏里面的目录结构,也不可对里面的文件改名,可以改目录名 My97DatePicker.htm是必须文件,不可删除 各目录及文件的用途:WdatePicker.js 配置文件,在调用的地方仅需使用该文件,可多个共存,以xx_WdatePicker.js方式命名con

layDate1.0正式发布,您一直在寻找的的js日期控件

你是时候换一款日期控件了,而layDate非常愿意和您成为工作伙伴.她正致力于成为全球最高大上的web日期支撑,为国内外所有从事web应用开发的同仁提供力所能及的动力.她基于原生JavaScript精心雕琢,兼容了包括IE6在内的所有主流浏览器.她具备优雅的内部代码,良好的性能体验,和完善的皮肤体系,并且完全开源,你可以任意获取开发版源代码,一扫某些传统日期控件的封闭与狭隘.layDate延续了layui一贯的简单与易用,本着资源共享的开发者精神和对网页日历交互的无穷追求,她将长年被维护和更新,