java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java日历可视化

java设计日历可视化的详细步骤记录

作者:筱姌

这篇文章主要给大家介绍了关于java设计日历可视化的相关资料,通过自定义的CircleLabel类来突出显示今天的日期,并使用BorderLayout布局管理窗口组件,文章详细描述了各个类和方法的设计思想和实现逻辑,需要的朋友可以参考下

设计目标

设计的这个日历既可以捕捉当天的日期,并且使用红色圆圈圈起来以及实时具体时间,而且将月份和年份设计了下拉框,可以自行选择具体的月份年份,也可以通过<和>两个按键实现对月份的转变,同时年份和月份的显示会随着按键转变而转变,本月日期用黑色标记清楚,其他月份日期用灰色标出。

实现功能

一、日历展示功能

二、年份选择功能

年下拉框:创建一个包含当前年份前后各 20 年的年份下拉框,用户可以从下拉框中选择特定的年份,选择后会自动更新显示相应年份的日历。

三、月份选择功能

月下拉框:创建一个包含十二个中文月份名称的下拉框,用户可以选择不同的月份来显示对应月份的日历。

四、实时时间显示功能

时间更新:使用定时器每秒钟更新一次窗口标题,显示当前的时间,格式为 “yyyy-MM-dd HH:mm:ss”,并带有时区设置为 “GMT+8”。

五、窗口布局和定位功能

设计类的思想

CalendarMain 类

整体设计目标

CalendarMain 类的主要目标是创建一个具有图形用户界面(GUI)的日历应用程序。它允许用户查看指定月份和年份的日历信息,能够切换月份,并且在窗口标题中实时显示当前时间。

成员变量设计思想

构造函数设计思想

CircleLabel 类(内部静态类)

整体设计目标

CircleLabel 类是一个自定义的标签类,继承自 JLabel。其主要设计目标是在日历应用程序中,针对表示当天日期的标签进行特殊绘制,使其呈现出圆形边框的效果,以便用户能够更直观地识别当天日期。

成员变量设计思想

构造函数设计思想

paintComponent 方法设计思想

displayCalendar 方法设计思想

changeMonth 方法设计思想

main 方法设计思想

updateTime 方法设计思想

getMonthName 方法设计思想

设计原理

.窗口布局和组件创建:

2.日历生成:

3.用户交互和时间更新:

功能实现

设计源码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.awt.RenderingHints;

// 定义主类 CalendarMain,继承自 JFrame 以创建可视化窗口
public class CalendarMain extends JFrame {
    // 月份标签,用于显示当前月份
    private final JLabel monthLabel;
    // 年份标签,用于显示当前年份
    private final JLabel yearLabel;
    // 日历面板,用于显示日历内容
    private final JPanel calendarPanel;
    // 当前月份的索引
    private int currentMonth;
    // 当前年份
    private int currentYear;
    // 当前时间的字符串表示
    private static String currentTime;

    // 年下拉框组件
    private JComboBox<Integer> yearComboBox;
    // 月下拉框组件
    private JComboBox<String> monthComboBox;

    public CalendarMain() {
        // 创建月份标签,初始显示为 "October 2023"
        monthLabel = new JLabel("October 2023");
        // 设置窗口标题为 "日历"
        setTitle("日历");
        // 设置窗口大小为 500x450 像素
        setSize(500, 450);
        // 设置窗口关闭操作,当关闭窗口时退出程序
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置窗口布局为 BorderLayout(边框布局)
        setLayout(new BorderLayout());

        // 获取屏幕尺寸
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenWidth = screenSize.width;
        int screenHeight = screenSize.height;
        // 计算窗口在屏幕中的位置,使其居中显示
        int x = (screenWidth - getWidth()) / 2;
        int y = (screenHeight - getHeight()) / 2;
        setLocation(x, y);

        // 获取当前时间的日历对象
        Calendar calendar = new GregorianCalendar();
        // 获取当前月份的索引
        currentMonth = calendar.get(Calendar.MONTH);
        // 获取当前年份
        currentYear = calendar.get(Calendar.YEAR);

        // 创建年下拉框
        yearComboBox = new JComboBox<>();
        // 循环添加从当前年份前后各 20 年的年份选项到年下拉框
        for (int i = currentYear - 20; i <= currentYear + 20; i++) {
            yearComboBox.addItem(i);
        }
        // 设置年下拉框的初始选中项为当前年份
        yearComboBox.setSelectedItem(currentYear);
        // 为年下拉框添加动作监听器,当选择年份变化时更新当前年份并重新显示日历
        yearComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                currentYear = (Integer) yearComboBox.getSelectedItem();
                displayCalendar();
            }
        });

        // 创建月下拉框
        monthComboBox = new JComboBox<>();
        // 创建包含中文月份名称的数组
        String[] monthNames = new String[]{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"};
        // 循环添加中文月份名称到月下拉框
        for (int i = 0; i < 12; i++) {
            monthComboBox.addItem(monthNames[i]);
        }
        // 设置月下拉框的初始选中项为当前月份对应的中文名称
        monthComboBox.setSelectedItem(monthNames[currentMonth]);
        // 为月下拉框添加动作监听器,当选择月份变化时更新当前月份并重新显示日历
        monthComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                currentMonth = monthComboBox.getSelectedIndex();
                displayCalendar();
            }
        });

        // 创建顶部面板,用于放置年、月下拉框和按钮等
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new FlowLayout());

        // 创建上一个月按钮,点击时调用 changeMonth(-1) 方法切换到上一个月
        JButton prevButton = new JButton("<");
        prevButton.addActionListener(e -> changeMonth(-1));
        topPanel.add(prevButton);

        // 将年下拉框添加到顶部面板
        topPanel.add(yearComboBox);
        // 将月下拉框添加到顶部面板
        topPanel.add(monthComboBox);

        // 创建年份标签(这里暂时保留原有的年份标签显示方式)
        yearLabel = new JLabel();
        topPanel.add(yearLabel);

        // 创建下一个月按钮,点击时调用 changeMonth(1) 方法切换到下一个月
        JButton nextButton = new JButton(">");
        nextButton.addActionListener(e -> changeMonth(1));
        topPanel.add(nextButton);

        // 将顶部面板添加到窗口的北侧(BorderLayout.NORTH)
        add(topPanel, BorderLayout.NORTH);

        // 创建一个 6 行 7 列的网格布局的面板,用于显示日历内容
        calendarPanel = new JPanel(new GridLayout(7, 7));
        // 将日历面板添加到窗口的中央(BorderLayout.CENTER)
        add(calendarPanel, BorderLayout.CENTER);

        // 显示日历内容
        displayCalendar();
        // 创建一个定时器,每 1000 毫秒(1 秒)触发一次更新时间的操作
        Timer timer = new Timer(1000, this::updateTime);
        timer.start();
    }

    // 自定义的圆形标签类,继承自 JLabel
    private static class CircleLabel extends JLabel {
        // 表示是否为今天的标志
        private boolean isToday;

        public CircleLabel(String text, boolean isToday) {
            // 调用父类构造方法,设置文本居中显示
            super(text, SwingConstants.CENTER);
            this.isToday = isToday;
            // 设置字体为 Arial,普通样式,字号为 20
            setFont(new Font("Arial", Font.PLAIN, 20));
        }

        @Override
        protected void paintComponent(Graphics g) {
            // 调用父类的 paintComponent 方法进行默认绘制
            super.paintComponent(g);
            // 如果是今天,则绘制红色圆形
            if (isToday) {
                Graphics2D g2d = (Graphics2D) g;
                // 设置抗锯齿渲染提示,使绘制的圆形更平滑
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                int width = getWidth();
                int height = getHeight();
                int diameter = Math.min(width, height);
                int x = (width - diameter) / 2;
                int y = (height - diameter) / 2;

                // 设置绘制颜色为红色
                g2d.setColor(Color.RED);
                // 绘制圆形
                g2d.drawOval(x, y, diameter, diameter);
            }
        }
    }

    private void displayCalendar() {
        // 清除日历面板上的所有组件
        calendarPanel.removeAll();

        // 创建当前月份的日历对象
        Calendar calendar = new GregorianCalendar(currentYear, currentMonth, 1);
        // 创建上一个月的日历对象
        Calendar prevMonth = new GregorianCalendar();
        if (currentMonth == 0) {
            // 如果当前月份是一月,则上一个月为去年的十二月
            prevMonth.set(currentYear - 1, 11, 1);
        } else {
            // 否则,上一个月为当前月份减一
            prevMonth.set(currentYear, currentMonth - 1, 1);
        }

        // 更新月份标签为当前月份的长名称
        monthLabel.setText(calendar.getDisplayName(Calendar.MONTH, Calendar.LONG, getLocale()));
        // 更新年份标签为当前年份
        yearLabel.setText(String.valueOf(currentYear));

        // 添加星期标题行
        String[] days = {"一", "二", "三", "四", "五", "六", "天"};
        for (String day : days) {
            // 创建星期标题标签并添加到日历面板
            calendarPanel.add(new JLabel(day, SwingConstants.CENTER));
        }

        // 获取当前月的第一天是星期几(星期日为 1,星期六为 7)
        int startDay = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        if (startDay == 0) startDay = 7;
        // 获取当前月的总天数
        int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        // 获取上一个月的总天数
        int prevDaysInMonth = prevMonth.getActualMaximum(Calendar.DAY_OF_MONTH);

        // 获取当前日期的日历对象
        Calendar todayCalendar = new GregorianCalendar();
        int todayDay = todayCalendar.get(Calendar.DAY_OF_MONTH);
        int todayMonth = todayCalendar.get(Calendar.MONTH);
        int todayYear = todayCalendar.get(Calendar.YEAR);

        // 添加上一个月的空白日期(灰色显示)
        for (int i = startDay - 1; i >= 1; i--) {
            JLabel label = new JLabel(String.valueOf(prevDaysInMonth - i + 1), SwingConstants.CENTER);
            label.setForeground(Color.GRAY);
            label.setFont(new Font("Arial", Font.PLAIN, 20));
            calendarPanel.add(label);
        }

        // 添加当前月的日期
        for (int i = 1; i <= daysInMonth; i++) {
            boolean isToday = (i == todayDay) && (currentMonth == todayMonth) && (currentYear == todayYear);
            // 创建日期标签,如果是今天则用圆形标签显示
            calendarPanel.add(new CircleLabel(String.valueOf(i), isToday));
        }

        // 填充后续的空白日期(灰色显示)
        for (int i = 1; i <= 42 - daysInMonth - (startDay - 1); i++) {
            JLabel dayLabel = new JLabel(String.valueOf(i), SwingConstants.CENTER);
            dayLabel.setForeground(Color.GRAY);
            dayLabel.setFont(new Font("Arial", Font.PLAIN, 20));
            calendarPanel.add(dayLabel);
        }

        // 重新验证和重绘日历面板
        calendarPanel.revalidate();
        calendarPanel.repaint();
    }

    // 切换月份的方法,delta 为正负 1 表示切换到上一个月或下一个月
    private void changeMonth(int delta) {
        currentMonth += delta;
        if (currentMonth < 0) {
            currentMonth = 11;
            currentYear--;
        } else if (currentMonth > 11) {
            currentMonth = 0;
            currentYear++;
        }
        // 更新年下拉框的选中项
        yearComboBox.setSelectedItem(currentYear);
        // 更新月下拉框的选中项
        monthComboBox.setSelectedItem(getMonthName(currentMonth));
        // 重新显示日历
        displayCalendar();
    }

    public static void main(String[] args) {
        // 使用 SwingUtilities.invokeLater 确保在事件分发线程中创建和显示窗口
        SwingUtilities.invokeLater(() -> {
            CalendarMain app = new CalendarMain();
            app.setVisible(true);
        });
    }

    // 更新时间的方法,每秒钟更新一次窗口标题显示的时间
    private void updateTime(ActionEvent e) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+8"));
        currentTime = sdf.format(new java.util.Date());
        setTitle("日历" + currentTime);
    }

    // 根据月份索引获取中文月份名称的方法
    private String getMonthName(int monthIndex) {
        String[] monthNames = new String[]{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"};
        return monthNames[monthIndex];
    }
}

总结 

到此这篇关于java设计日历可视化的文章就介绍到这了,更多相关java日历可视化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文