Java Swing 日历 控件
这是我改写的网上的DateChooser代码后的作品,使用效果如图所示。用法参考备注,以及Main函数中用法。
/**
*
* Copyright: Ares.
* All Rights Reserved.
* Company: Insigma HT/上海创图
* @author Ares <a href="mailto:icerainsoft@hotmail.com>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 日历 控件的更多相关文章
- Java Swing 日期控件(转载)
http://www.cnblogs.com/lzy1991/p/5714935.html
- 【转】【WebDriver】不可编辑域和日历控件域的输入 javascript
http://blog.csdn.net/fudax/article/details/8089404 今天用到日历控件,用第一个javascript执行后页面上的日期控件后,在html中可以看到生效日 ...
- Selenium2+python自动化25-js处理日历控件(修改readonly属性)
前言 日历控件是web网站上经常会遇到的一个场景,有些输入框是可以直接输入日期的,有些不能,以我们经常抢票的12306网站为例,详细讲解如何解决日历控件为readonly属性的问题. 基本思路:先用j ...
- android日历控件(一)
自定义日历并且具备设置今天以前的时间不可点选,以前的颜色和当前的颜色不同,以及获取两次点击日期之间间隔的天数所以说细节比较多 个人习惯,先上图 靠,笔记本不知道怎么回事,禁用到触摸板之后 再次唤醒屏幕 ...
- 推荐一款JavaScript日历控件:kimsoft-jscalendar
一.什么是 kimsoft-jscalendar 一个简洁的avaScript日历控件,可在Java Web项目,.NET Web 项目中使用 二.kimsoft-jscalendar 有什么 ...
- My97DatePicker日历控件日报、每周和每月的选择
My97DatePicker日历控件日报.每周和每月的选择 1.设计源代码 <%@ page language="java" import="java.util.* ...
- Android自己定义组件之日历控件-精美日历实现(内容、样式可扩展)
需求 我们知道.Android系统本身有自带的日历控件,网络上也有非常多开源的日历控件资源.可是这些日历控件往往样式较单一.API较多.不易于在实际项目中扩展并实现出符合详细样式风格的,内容可定制的效 ...
- Android 一个日历控件的实现代码
转载 2017-05-19 作者:Othershe 我要评论 本篇文章主要介绍了Android 一个日历控件的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看 ...
- 简洁js日历控件的使用
往Web工程添加纯js日历控件 在网上找到了DatePicker.js(http://www.cnblogs.com/shenyixin/archive/2013/03/11/2954156.html ...
随机推荐
- memcached+Mysql(主从)
昨天和守住看了下http://hi.baidu.com/156544632/blog/item/3b26527b68623ff00bd18746.html这篇文章,思路很好,但感觉就是太乱了,而且还出 ...
- unity, 忽略碰撞
一,layer之间忽略碰撞. Edit->Project Settings->Physics->Layer Collision Matrix 二,collider之间忽略碰撞. vo ...
- Redis(十三):Redis分布式锁的正确实现方式
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- 超NB的WINDWS命令 当插移动硬盘时 自动弹出要格式化硬盘
其中d表示无法识别的那个盘的盘符 移动磁盘修复成功
- Windows Phone 性能优化(一)
在实际的项目开发过程中,应用的性能优化是一个永恒的话题,也是开发者群里最常讨论的话题之一,我在之 前的公司做 wp项目时,也遇到过性能的瓶颈.当页面中加载的内容越来越多时,内存涨幅非常明显(特别是 一 ...
- jquery的商品首页
js代码: $(function() { /*新闻滚动*/ var $this = $('.scrollNews'); var scrollTimer; $this.hover(function () ...
- 10个Python 统计报表/图表图形类库
matplotlib,官网:http://matplotlib.sourceforge.net/,Matplotlib 是一个由 John Hunter 等开发的,用以绘制二维图形的 Python 模 ...
- python学习笔记(11)--爬虫下载漫画图片
说明: 1. 某本子网站爬虫,现在只实现了扒取一页,已经凌晨两点了,又饿又困,先睡觉,明天再写总结吧! 2. 我是明天,我来写总结了! 3. 这个网站的结构是这样的: 主页: 主页-第1页-漫画1封面 ...
- Bootstrap学习笔记(5)--实现Bootstrap导航条可点击和鼠标悬停显示下拉菜单
实现Bootstrap导航条可点击和鼠标悬停显示下拉菜单 微笑的鱼 2014-01-03 Bootstrap 5,281 次围观 11条评论 使用Bootstrap导航条组件时,如果你的导航条带有下拉 ...
- [转]Python中函数的值传递和引用传递
首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...