You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JCalendar中今日日期无法高亮的问题排查与修复请求

问题原因与修复方案

核心问题分析

  1. 时间戳匹配失败:你存储的作业日期被处理为00:00:00的时间戳,但JCalendar传递给isSpecial方法的今日日期是包含当前时分秒的完整时间戳。Date.equals方法比较的是完整时间戳,导致两者不匹配,assignmentDates.contains(date)返回false,今日未被标记为特殊日期。
  2. 默认样式优先级覆盖:即使解决了时间戳问题,JCalendar默认的今日单元格样式(比如背景色)会优先绘制,可能覆盖你自定义的特殊日期高亮。

修复步骤

1. 修改isSpecial方法,按日期(年/月/日)匹配

替换原Evaluator类中的isSpecial方法,不再依赖Date.contains,而是直接比较年、月、日三个字段:

@Override
public boolean isSpecial(Date date) {
    Calendar targetCal = Calendar.getInstance();
    targetCal.setTime(date);
    for (Date assignDate : assignmentDates) {
        Calendar assignCal = Calendar.getInstance();
        assignCal.setTime(assignDate);
        if (targetCal.get(Calendar.YEAR) == assignCal.get(Calendar.YEAR)
                && targetCal.get(Calendar.MONTH) == assignCal.get(Calendar.MONTH)
                && targetCal.get(Calendar.DAY_OF_MONTH) == assignCal.get(Calendar.DAY_OF_MONTH)) {
            return true;
        }
    }
    return false;
}

2. 解决默认样式覆盖问题(二选一)

方案A:通过UIManager移除默认今日背景

在程序启动时添加以下配置,让默认今日背景透明,避免覆盖自定义高亮:

UIManager.put("Calendar.dayTodayBackground", new Color(0,0,0,0)); // 透明背景
UIManager.put("Calendar.dayTodayForeground", Color.BLACK); // 保留文字颜色

方案B:自定义DayChooser控制绘制顺序

重写DayChooser的paintDay方法,确保特殊日期的样式优先绘制:

static class CustomDayChooser extends com.toedter.calendar.DayChooser {
    public CustomDayChooser() {
        super();
    }

    @Override
    protected void paintDay(Graphics g, int x, int y, int w, int h, Date day, boolean isSelected, boolean isToday, boolean isWeekend, boolean isFocused) {
        // 先检查是否为特殊日期,优先绘制
        for (IDateEvaluator evaluator : getDateEvaluators()) {
            if (evaluator.isSpecial(day)) {
                g.setColor(evaluator.getSpecialBackroundColor());
                g.fillRect(x, y, w, h);
                g.setColor(evaluator.getSpecialForegroundColor());
                g.drawString(String.valueOf(getDayOfMonth(day)), x + w / 2 - 4, y + h / 2 + 5);
                return;
            }
        }
        // 非特殊日期执行默认绘制逻辑
        super.paintDay(g, x, y, w, h, day, isSelected, isToday, isWeekend, isFocused);
    }
}

然后在创建JCalendar时替换默认DayChooser:

JCalendar jc = new JCalendar();
jc.setDayChooser(new CustomDayChooser());

完整修复代码

整合所有修改后的完整代码如下:

import com.toedter.calendar.IDateEvaluator;
import com.toedter.calendar.JCalendar;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.UIManager;

public class calendar {

    private static class Evaluator implements IDateEvaluator {
        private List<Date> assignmentDates = new ArrayList<>();

        public void add(Date dates) {
            assignmentDates.add(dates);
        }

        public void remove(Date date) {
            assignmentDates.remove(date);
        }

        public void setDates(List<Date> dates) {
            assignmentDates.addAll(dates);
        }

        @Override
        public boolean isSpecial(Date date) {
            Calendar targetCal = Calendar.getInstance();
            targetCal.setTime(date);
            for (Date assignDate : assignmentDates) {
                Calendar assignCal = Calendar.getInstance();
                assignCal.setTime(assignDate);
                if (targetCal.get(Calendar.YEAR) == assignCal.get(Calendar.YEAR)
                        && targetCal.get(Calendar.MONTH) == assignCal.get(Calendar.MONTH)
                        && targetCal.get(Calendar.DAY_OF_MONTH) == assignCal.get(Calendar.DAY_OF_MONTH)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public Color getSpecialForegroundColor() {
            return Color.WHITE;
        }

        @Override
        public String getSpecialTooltip() {
            return "Highlighted Event";
        }

        @Override
        public boolean isInvalid(Date date) {
            return false;
        }

        @Override
        public Color getInvalidForegroundColor() {
            return null;
        }

        @Override
        public Color getInvalidBackroundColor() {
            return null;
        }

        @Override
        public String getInvalidTooltip() {
            return null;
        }

        @Override
        public Color getSpecialBackroundColor() {
            return Color.MAGENTA;
        }
    }

    static class CustomDayChooser extends com.toedter.calendar.DayChooser {
        public CustomDayChooser() {
            super();
        }

        @Override
        protected void paintDay(Graphics g, int x, int y, int w, int h, Date day, boolean isSelected, boolean isToday, boolean isWeekend, boolean isFocused) {
            for (IDateEvaluator evaluator : getDateEvaluators()) {
                if (evaluator.isSpecial(day)) {
                    g.setColor(evaluator.getSpecialBackroundColor());
                    g.fillRect(x, y, w, h);
                    g.setColor(evaluator.getSpecialForegroundColor());
                    g.drawString(String.valueOf(getDayOfMonth(day)), x + w / 2 - 4, y + h / 2 + 5);
                    return;
                }
            }
            super.paintDay(g, x, y, w, h, day, isSelected, isToday, isWeekend, isFocused);
        }
    }

    private void display() {
        List<Date> datesList = new ArrayList<>();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        try {
            datesList.add(dateFormat.parse("2025-03-06"));
            datesList.add(dateFormat.parse("2025-03-24"));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        JFrame f = new JFrame("Calendar");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JCalendar jc = new JCalendar();
        jc.setDayChooser(new CustomDayChooser());

        List<Date> dates = new ArrayList<>();
        for (Date d : datesList) {
            dates.add(createDate(d));
        }

        Evaluator evaluator = new Evaluator();
        evaluator.setDates(dates);
        jc.getDayChooser().addDateEvaluator(evaluator);

        f.add(jc);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        jc.repaint();
    }

    private Date createDate(Date d) {
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    public static void main(String[] args) {
        try {
            UIManager.put("Calendar.dayTodayBackground", new Color(0,0,0,0));
            UIManager.put("Calendar.dayTodayForeground", Color.BLACK);

            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        EventQueue.invokeLater(new calendar()::display);
    }
}

内容的提问来源于stack exchange,提问作者luna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:30:54