Java实现日历

代码:

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.*;

public class Calendar extends JFrame{
    private static final String[] WEEK={"星期一","星期二","星期三","星期四","星期五","星期六","星期日"};

    //当前日期
    private LocalDate currentDate=LocalDate.now();

    //年份和月份选择器
    private JComboBox<Integer> yearSelector;
    private JComboBox<Integer> monthSelector;

    //日历表格
    private JTable calTable;
    private DefaultTableModel tableModel;

    /**
     * 构造器,显示日历窗口
     */

    public Calendar(){
        this.setTitle("Calendar");
        this.setLayout(new BorderLayout());
        //创建年份月份选择器
        yearSelector=new JComboBox<>();
        for(int i=1900;i<=2100;i++){
            yearSelector.addItem(i);
        }
        yearSelector.setSelectedItem(currentDate.getYear());
        yearSelector.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tableUpDate();
            }
        });
        monthSelector=new JComboBox<>();
        for(int i=1;i<=12;i++){
            monthSelector.addItem(i);
        }
        monthSelector.setSelectedItem(currentDate.getMonth().getValue());

        monthSelector.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tableUpDate();
            }
        });

        //将选择器添加到面板上
        JPanel panel1=new JPanel(new FlowLayout());
        panel1.add(yearSelector);
        panel1.add(monthSelector);
        this.add(BorderLayout.NORTH,panel1);

        /**创建表格*/
        //设置表格不可编辑
        tableModel=new DefaultTableModel(6,7){
            public boolean isCellEditable(int row,int column){
                return false;
            }
        };

        tableModel.insertRow(0,WEEK);

        //设置表格基本属性
        calTable = new JTable(tableModel);
        calTable.setPreferredScrollableViewportSize(new Dimension(500, 250));
        calTable.setRowHeight(30);
        calTable.setGridColor(Color.BLACK);
        calTable.setSelectionBackground(new Color(175, 212, 255));
        calTable.setFont(new Font("黑体", Font.PLAIN, 16));
        calTable.setShowGrid(true);
        calTable.setCellSelectionEnabled(true);
        calTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        calTable.getTableHeader().setReorderingAllowed(false);
        JPanel panel2=new JPanel(new FlowLayout());
        panel2.add(calTable);
        this.add(panel2);
        JScrollPane scrollPane = new JScrollPane(calTable);
        this.add(scrollPane, BorderLayout.CENTER);
        this.pack();
        this.setLocationRelativeTo(null); // 居中显示
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        tableUpDate();
    }


    /**
     * 更新表格的方法
     * @param
     */

    public void tableUpDate(){
        //清空表格
        tableModel.setRowCount(0);
        //获取日期
        int month=monthSelector.getSelectedIndex()+1;
        int year=(int)yearSelector.getSelectedItem();


        // 获取该月的天数
        int daysInMonth = YearMonth.of(year, month).lengthOfMonth();


        // 获取该月第一天的星期几
        LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
        DayOfWeek firstDayOfWeek = firstDayOfMonth.getDayOfWeek();
        int offset = firstDayOfWeek.getValue();
        //System.out.println(firstDayOfWeek);


        //重绘表格
        tableModel.insertRow(0,WEEK);
        for(int i=0;i<6;i++) {
            tableModel.addRow(new Object[7]);
        }

        //向表格中添加日期
        int rowIndex=1;
        int dayIndex=offset-1;
        int tableIndex=offset;
        for(int i=1;i<=daysInMonth;i++,tableIndex++){
           // System.out.println(dayIndex);
            tableModel.setValueAt(i,rowIndex,dayIndex);
            dayIndex++;
            //自定义一个表格渲染器,对当前日期的单元格背景颜色进行修改
            DefaultTableCellRenderer ter=new DefaultTableCellRenderer(){
                @Override
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
                    Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                    if (month == LocalDate.now().getMonthValue()&&value != null && value instanceof Integer && (Integer) value == currentDate.getDayOfMonth()) {
                        setBackground(Color.GRAY);
                    } else {
                        setBackground(null);
                    }
                    return c;
                }
            };
            calTable.getColumnModel().getColumn(tableIndex % 7).setCellRenderer(ter);
            if(tableIndex%7==0){
                rowIndex++;//换行
                dayIndex=0;//重置表格单元格索引
            }

        }
    }

    public static void main(String[] args){
        new Calendar();
    }
}

展示效果:

 通过展示效果可以看出来,这个日历UI主要通过表格(JTable)、下拉框(JComboBox)来实现的。

对于下拉框,我们可以创建两个下拉框组件并添加到面板上,调用addItem方法向其中添加日期。

对于日期,我们需要考虑两个方面:

  1. 判断该年是否为闰年,该月有几天?
  2. 判断该月的第一天是星期几?

1.判断闰年和月份天数

 我们可以直接写出两个方法来判断。如下:

 

public int getDaysInMonth(int year,int month){
        switch (month){
            case 2:
                return (isLeapYear(year)?29:28);
            case 4:
            case 6:
            case 9:
            case 11:
                return 30;
            default:
                return 31;
        }
    }

    public boolean isLeapYear(int year) {
        if((year%4==0&&year%100!=0)||year%400==0){
            return true;
        }
        return false;
    }

 2.判断该月的第一天是星期几

已知的一种计算方法:我们每个月的第一天是接着上个月的最后一天的,然后我们知道1900年的1月1日是星期一,那我们可以把从1900年到我们指定日期的前一个月的总天数求出来对7取余,就是上一个月最后一天的星期数(也是这个月开始前面的空格数)。

所以有如下:

 

public int getFirstDayOfWeek(int year,int month){
        int pastDays=0;
        for(int i=1900;i<year;i++){
            pastDays+=isLeapYear(i)?366:365;
        }
        for(int i=1;i<month;i++){
            pastDays+=getDaysInMonth(year,i);
        }
        return pastDays%7;

    }

看起来是不是非常简单呢。

3.如何让日历可更新

我们windows或者mac自带的日历都是可以看非当前月份的日历,所以才叫做万年历。那么我们该如何实现呢?

下拉框的作用是让我们选择日期,我们可以给下拉框组件添加事件监听,如果使用下拉框进行选择日期,则调用一个表格更新(tableUpDate)方法。

代码示例如下:

 public void tableUpDate(){
        //清空表格
        tableModel.setRowCount(0);
        //获取日期
        int month=monthSelector.getSelectedIndex()+1;
        int year=(int)yearSelector.getSelectedItem();


        // 获取该月的天数
        int daysInMonth = getDaysInMonth(year,month);


        // 获取该月第一天的星期几
        int offset=getFirstDayOfWeek(year,month)+1;


        //重绘表格
        tableModel.insertRow(0,WEEK);
        for(int i=0;i<6;i++) {
            tableModel.addRow(new Object[7]);
        }

        //向表格中添加日期
        int rowIndex=1;
        int dayIndex=offset-1;
        int tableIndex=offset;
        for(int i=1;i<=daysInMonth;i++,tableIndex++){
           // System.out.println(dayIndex);
            tableModel.setValueAt(i,rowIndex,dayIndex);
            dayIndex++;
            //自定义一个表格渲染器,对当前日期的单元格背景颜色进行修改
            DefaultTableCellRenderer ter=new DefaultTableCellRenderer(){
                @Override
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
                    Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                    if (month == LocalDate.now().getMonthValue()&&value != null && value instanceof Integer && (Integer) value == currentDate.getDayOfMonth()) {
                        setBackground(Color.GRAY);
                    } else {
                        setBackground(null);
                    }
                    return c;
                }
            };
            calTable.getColumnModel().getColumn(tableIndex % 7).setCellRenderer(ter);
            if(tableIndex%7==0){
                rowIndex++;//换行
                dayIndex=0;//重置表格单元格索引
            }

        }
    }

 soga~。这就是一个可更新的日历实现方法,多尝试、多思考,努力成为大佬!!!

使用 Java 实现日历功能有多种方式,以下为你介绍常见的实现方法及示例代码: ### 控制台输出简单日历 可以使用 `GregorianCalendar` 类来实现一个简单的控制台日历。下面是一个示例代码: ```java import java.util.Calendar; import java.util.GregorianCalendar; import java.sql.Date; public class CalendarExample { public void showTime(String time) { Date localDate = java.sql.Date.valueOf(time); Calendar calendar = new GregorianCalendar(); calendar.setTime(localDate); // 获取当月最大天数 int maxDay = calendar.getActualMaximum(Calendar.DATE); // 获取当前 day int localDay = calendar.get(Calendar.DATE); // 将 day 设置为 1 calendar.set(Calendar.DATE, 1); // 获取当前天数在周内的第几天 int dayInWeek = calendar.get(Calendar.DAY_OF_WEEK); System.out.println("日\t一\t二\t三\t四\t五\t六"); for (int black = 0; black < dayInWeek - 1; black++) { System.out.print("\t"); } for (int day = 1; day <= maxDay; day++) { if (day == localDay) { System.out.print(day + "*" + "\t"); } else { System.out.print(day + "\t"); } if ((day + dayInWeek - 1) % 7 == 0) { System.out.println(); } } } public static void main(String[] args) { CalendarExample example = new CalendarExample(); example.showTime("2024-01-01"); } } ``` 此代码通过 `GregorianCalendar` 类获取指定日期所在月份的信息,包括最大天数、当前日期等,然后在控制台输出该月的日历,当前日期会用 `*` 标记 [^1]。 ### Java GUI 实现万年历 使用 Java Swing 可以实现一个图形界面的日历万年历。通常会使用三个类,一个 bean 类实现基本的日期计算,一个界面类实现界面渲染,另一个主类用于启动。虽然没有给出完整代码,但整体思路是通过日期计算类计算日期信息,界面类将这些信息渲染到图形界面上,实现可以显示任何一年日期信息的万年历 [^2]。 ### 日历记事本功能实现 可以实现一个带有记事本功能的日历。该日历可以通过在文本框中输入年份和月份设置日期,也可按年前后翻动(用鼠标左键单击“上年”和“下年”按钮,将当前日历的年份减一和加一),还能在某年内按月前后翻动(用鼠标左键单击“上月”和“下月”按钮,将日历的月份减一和加一) [^3]。 ### 日历可视化设计 使用 `GregorianCalendar` 类获取当前时间和特定月份的日历信息。通过计算当前月的第一天是星期几以及该月的总天数,生成日历的布局。对于上一个月和下一个月的空白日期,使用灰色字体显示上一个月的日期或下一个月的占位符;对于当前月的日期,使用自定义的圆形标签突出显示今天的日期 [^4]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值