最近用Java图形界面编程,在日历的时候没有合适的模板,在网上找了点demo来进行修改,做成自己使用的模板,不多说了,先上一个效果图如下所示:
直接上代码部分:
/**
* 自定义日历类
* @author James
*2017年4月2日
*/
public class CanlendarDate 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 = { "日", "一", "二", "三", "四", "五", "六" };
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 CanlendarDate(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 CanlendarDate getInstance(java.util.Date date, String format) {
return new CanlendarDate(date, format, defaultStartDAY);
}
public static CanlendarDate getInstance(java.util.Date date) {
return getInstance(date, DEFAULTFORMAT);
}
public static CanlendarDate getInstance(String format) {
return getInstance(new java.util.Date(), format);
}
public static CanlendarDate 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("今天是 : " + 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<CanlendarDate.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);
}
}
}
}
调用部分代码:
/**
* 生日
*/
private void birthday() {
// date = new LovoDate("生日", 20, 230, this);
CanlendarDate ser = CanlendarDate.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date today = new Date(); // 今天
JLabel birthdayLabel = new JLabel("生\0\0日:");
birthdayLabel.setBounds(20, 230, 50, 20);
JTextField mBirthday = new JTextField();
mBirthday.setBounds(70, 230, 200, 20);
mBirthday.setText(formatter.format(today));
ser.register(mBirthday);
contentPane.add(birthdayLabel);
contentPane.add(mBirthday);
}
上面只列举了其中的一种掉用方法,还可以下面的方法进行日历的初始化:
CanlendarDate ser2 = CanlendarDate.getInstance("yyyy年MM月dd日");
具体用什么方法调用就是
ser.register(mBirthday);