记一个JFrame日历组件
前言
因编写插件需要一个日历展示界面用于选择日期,因此编写该组件
代码
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class JPanelByCalendar extends JPanel {
String[] weekName=new String[]{"一","二","三","四","五","六","日"};
private int status=0;//0日期,1月份,2年份
private LocalDate focusDate;
private JLabel focusDayJLabel;
private LocalDate nowDate=LocalDate.now();
private JLabel nowMonthJLabel;
private JLabel head;//头部容器
private JPanel yearJPanel;//年份显示容器
private List<JLabel> yearJLabel=new ArrayList<>(12);
private JPanel monthJPanel;//月份显示容器
private List<JLabel> monthJLabel=new ArrayList<>(12);
private JPanel dayJPanel;//日期显示容器
private List<JLabel> dayJLabel=new ArrayList<>(49);
private JLabel viewJLabel;//动态显示月份/年份
private JLabel upJLabel;//上一页按钮
private JLabel downJLabel;//下一页按钮
public JPanelByCalendar() {
super();
this.setLayout(null);
head = new JLabelForImage();
head.setBounds(0,0,300,50);
// 获取当前日期
LocalDate currentDate = LocalDate.now();
focusDate=currentDate;
int year = currentDate.getYear();
int month = currentDate.getMonthValue();
int dayOfMonth = currentDate.getDayOfMonth();
String dayOfWeek = currentDate.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault());
JLabel nowDateJLabel=new JLabel(String.format("%s年%s月%s日,%s",year,month,dayOfMonth,dayOfWeek));
nowDateJLabel.setBounds(0,0,300,20);
nowDateJLabel.setHorizontalAlignment(JLabel.CENTER);
nowDateJLabel.setOpaque(true);
nowDateJLabel.setBackground(Color.LIGHT_GRAY);
viewJLabel=new JLabel(String.format("\t%s年%s月",year,month));
viewJLabel.addMouseListener(new MouseUpListener(viewJLabel,0) {
@Override
public void mouseClicked(MouseEvent e) {
//修改选框
if(status==0){
status=1;
//展示月份
refreshMonthJPanel();
JPanelByCalendar.this.remove(1);
JPanelByCalendar.this.add(monthJPanel,1);
JPanelByCalendar.this.repaint();
}else if(status==1){
status=2;
//展示年份
refreshYearJPanel();
JPanelByCalendar.this.remove(1);
JPanelByCalendar.this.add(yearJPanel,1);
JPanelByCalendar.this.repaint();
}
}
});
viewJLabel.setBounds(15,22,170,24);
viewJLabel.setOpaque(true);
// viewJLabel.setBackground(Color.lightGray);
//向上翻页
upJLabel=new JLabel("㊤");
upJLabel.addMouseListener(new MouseUpListener(upJLabel,0) {
@Override
public void mouseClicked(MouseEvent e) {
if(status==0){
focusDate=focusDate.minusMonths(1);
refreshDayJPanel();
}else if(status==1){
focusDate=focusDate.minusYears(1);
refreshMonthJPanel();
}else {
focusDate=focusDate.minusYears(16);
refreshYearJPanel();
}
JPanelByCalendar.this.repaint();
}
});
upJLabel.setBounds(195,22,40,24);
upJLabel.setOpaque(true);
// upJLabel.setBackground(Color.lightGray);
upJLabel.setHorizontalAlignment(JLabel.CENTER);
//向下翻页
downJLabel=new JLabel("㊦");
downJLabel.addMouseListener(new MouseUpListener(downJLabel,0) {
@Override
public void mouseClicked(MouseEvent e) {
if(status==0){
focusDate=focusDate.plusMonths(1);
refreshDayJPanel();
}else if(status==1){
focusDate=focusDate.plusYears(1);
refreshMonthJPanel();
}else {
focusDate=focusDate.plusYears(16);
refreshYearJPanel();
}
JPanelByCalendar.this.repaint();
}
});
downJLabel.setBounds(245,22,40,24);
downJLabel.setOpaque(true);
// downJLabel.setBackground(Color.lightGray);
downJLabel.setHorizontalAlignment(JLabel.CENTER);
head.add(nowDateJLabel,0);
head.add(upJLabel,1);
head.add(downJLabel,2);
head.add(viewJLabel,3);
head.setBorder(BorderFactory.createMatteBorder(0,0,2,0,Color.gray));
this.add(head,0);
//初始化年份
yearJPanel=new JPanel();
yearJPanel.setLayout(new GridLayout(4,4));
yearJPanel.setBounds(0,50,300,212);
yearJPanel.setBorder(BorderFactory.createLineBorder(Color.gray,1));
for (int i = year; i <year+16; i++) {
JLabel jLabel = new JLabel();
jLabel.setOpaque(true);
jLabel.setBackground(Color.white);
jLabel.setHorizontalAlignment(JLabel.CENTER);
jLabel.addMouseListener(new MouseUpListener(jLabel) {
@Override
public void mouseClicked(MouseEvent e) {
status=1;
jLabel.setBackground(Color.white);
int year = Integer.valueOf(jLabel.getText());
focusDate=LocalDate.ofYearDay(year,1);
//展示月份
refreshMonthJPanel();
JPanelByCalendar.this.remove(1);
JPanelByCalendar.this.add(monthJPanel,1);
JPanelByCalendar.this.repaint();
}
});
yearJLabel.add(jLabel);
yearJPanel.add(jLabel);
}
//初始化月份
monthJPanel=new JPanel();
monthJPanel.setLayout(new GridLayout(3,4));
monthJPanel.setBounds(0,50,300,212);
monthJPanel.setBorder(BorderFactory.createLineBorder(Color.gray,1));
for (int i = 1; i <= 12; i++) {
JLabel jLabel = new JLabel();
jLabel.setOpaque(true);
jLabel.setBackground(Color.white);
jLabel.setHorizontalAlignment(JLabel.CENTER);
jLabel.setText(String.valueOf(i));
jLabel.addMouseListener(new MouseUpListener(jLabel) {
@Override
public void mouseClicked(MouseEvent e) {
status=0;
jLabel.setBackground(Color.white);
int month = Integer.valueOf(jLabel.getText());
focusDate=focusDate.withMonth(month).withDayOfMonth(1);
//展示日期
refreshDayJPanel();
JPanelByCalendar.this.remove(1);
JPanelByCalendar.this.add(dayJPanel,1);
JPanelByCalendar.this.repaint();
}
});
monthJPanel.add(jLabel);
monthJLabel.add(jLabel);
}
//初始化日期
dayJPanel=new JPanel();
dayJPanel.setLayout(new GridLayout(7,7));
dayJPanel.setBounds(0,50,300,212);
dayJPanel.setBorder(BorderFactory.createLineBorder(Color.gray,1));
for (int i = 0; i < 49; i++) {
JLabel jLabel = new JLabel();
jLabel.setOpaque(true);
jLabel.setBackground(Color.white);
jLabel.setHorizontalAlignment(JLabel.CENTER);
if(i<7){
jLabel.setText(weekName[i]);
}else{
jLabel.addMouseListener(new MouseUpListener(jLabel){
@Override
public void mouseClicked(MouseEvent e) {
if(jLabel.getText()!=null&&jLabel.getText().length()>0){
focusDayJLabel.setBorder(null);
focusDate=focusDate.withDayOfMonth(Integer.valueOf(jLabel.getText()));
jLabel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
focusDayJLabel=jLabel;
}
}
});
}
dayJLabel.add(jLabel);
dayJPanel.add(jLabel);
}
refreshDayJPanel();
this.add(dayJPanel,1);
}
//刷新日期
void refreshDayJPanel(){
//初始化
for (int i = 0; i < 49; i++) {
if(i<7)continue;
JLabel jLabel = dayJLabel.get(i);
jLabel.setBorder(null);
jLabel.setForeground(null);
jLabel.setText("");
}
//获取当月数据
LocalDate localDate = focusDate.withDayOfMonth(1);
int year = localDate.getYear();
int month = localDate.getMonthValue();
viewJLabel.setText(String.format("\t%s年%s月",year,month));
Boolean nowFlag=false;
if(year== nowDate.getYear()&&month==nowDate.getMonthValue()){
nowFlag=true;
}
int week = localDate.getDayOfWeek().getValue();
int days = localDate.lengthOfMonth();
int focusDay=focusDate.getDayOfMonth();
int start=week+6;
//循环写入
for (int i = 0;i<days;i++){
JLabel jLabel = dayJLabel.get(start + i);
jLabel.setText(String.valueOf(i+1));
if(focusDay==i+1){
focusDayJLabel=jLabel;
jLabel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
}
if(nowFlag&&nowDate.getDayOfMonth()==i+1){
jLabel.setForeground(Color.BLUE);
}
}
}
//刷新月份
void refreshMonthJPanel(){
int year = focusDate.getYear();
viewJLabel.setText(String.format("\t%s年",year));
//设置当前月高亮显示
if(year== nowDate.getYear()) {
nowMonthJLabel = monthJLabel.get(nowDate.getMonth().getValue() - 1);
nowMonthJLabel.setForeground(Color.BLUE);
}else{
if(nowMonthJLabel!=null)nowMonthJLabel.setForeground(null);
}
}
//刷新年份
void refreshYearJPanel(){
yearJLabel.forEach(jLabel -> {
jLabel.setText("");
jLabel.setForeground(null);
});
int year = focusDate.getYear();
int nowYear=nowDate.getYear();
viewJLabel.setText(String.format("\t%s年-%s年",year,year+15));
for (int i = 0; i <16; i++) {
JLabel jLabel = yearJLabel.get(i);
jLabel.setText(String.valueOf(year+i));
if(nowYear==year+i){
jLabel.setForeground(Color.BLUE);
}
}
}
public LocalDate getFocusDate() {
return focusDate;
}
public static void main(String[] args) {
Toolkit kit=Toolkit.getDefaultToolkit();
Dimension sc=kit.getScreenSize();
JFrame jFrame=new JFrame();
int width=sc.width;
int height=sc.height;
jFrame.setBounds((width-313)/2,(height-300)/2,313,300);
JPanel calendar = new JPanelByCalendar();
jFrame.setContentPane(calendar);
jFrame.setVisible(true);
}
abstract class MouseUpListener extends MouseAdapter{
private JLabel jLabel;
private Integer type=-1;
public MouseUpListener(JLabel jLabel) {
this.jLabel = jLabel;
}
public MouseUpListener(JLabel jLabel,Integer type) {
this.jLabel = jLabel;
this.type=type;
}
@Override
public void mouseEntered(MouseEvent e) {
jLabel.setBackground(Color.lightGray);
}
@Override
public void mouseExited(MouseEvent e) {
if(type==0){
jLabel.setBackground(null);
}else {
jLabel.setBackground(Color.white);
}
}
}
}
说明
该代码使用JPanel实现,选择年份,月份,日期