java設(shè)計日歷可視化的詳細(xì)步驟記錄
設(shè)計目標(biāo)
設(shè)計的這個日歷既可以捕捉當(dāng)天的日期,并且使用紅色圓圈圈起來以及實時具體時間,而且將月份和年份設(shè)計了下拉框,可以自行選擇具體的月份年份,也可以通過<和>兩個按鍵實現(xiàn)對月份的轉(zhuǎn)變,同時年份和月份的顯示會隨著按鍵轉(zhuǎn)變而轉(zhuǎn)變,本月日期用黑色標(biāo)記清楚,其他月份日期用灰色標(biāo)出。
實現(xiàn)功能
一、日歷展示功能
- 可視化日歷:創(chuàng)建一個可視化的日歷窗口,展示特定月份的日歷布局,包括星期幾的標(biāo)題行和日期格子。
- 月份切換:通過 “<” 和 “>” 按鈕可以切換到上一個月或下一個月的日歷。同時,也可以通過年和月的下拉框選擇特定的年份和月份來顯示相應(yīng)的日歷。
- 突出顯示今天:在日歷中,用紅色圓形突出顯示當(dāng)天的日期,方便用戶快速識別。
- 顯示月份名稱:在窗口頂部顯示當(dāng)前月份的中文名稱,如 “一月”“二月” 等。
- 日期范圍調(diào)整:對于當(dāng)前月份之前的日期(上一個月的日期),以灰色字體顯示在日歷的開頭部分;對于當(dāng)前月份之后的日期(下一個月的占位符),也以灰色字體顯示在日歷的結(jié)尾部分。
二、年份選擇功能
年下拉框:創(chuàng)建一個包含當(dāng)前年份前后各 20 年的年份下拉框,用戶可以從下拉框中選擇特定的年份,選擇后會自動更新顯示相應(yīng)年份的日歷。
三、月份選擇功能
月下拉框:創(chuàng)建一個包含十二個中文月份名稱的下拉框,用戶可以選擇不同的月份來顯示對應(yīng)月份的日歷。
四、實時時間顯示功能
時間更新:使用定時器每秒鐘更新一次窗口標(biāo)題,顯示當(dāng)前的時間,格式為 “yyyy-MM-dd HH:mm:ss”,并帶有時區(qū)設(shè)置為 “GMT+8”。
五、窗口布局和定位功能
- 窗口布局:使用
BorderLayout
布局將窗口分為頂部和中央兩部分,頂部放置年、月下拉框、按鈕和年份標(biāo)簽,中央放置日歷面板。 - 窗口定位:在程序啟動時,自動計算窗口在屏幕中的位置,使其居中顯示。
設(shè)計類的思想
- 可視化日歷應(yīng)用:CalendarMain類旨在創(chuàng)建一個可視化的日歷應(yīng)用程序,提供用戶交互功能,允許用戶通過年、月下拉框和按鈕切換不同的月份和年份,同時實時顯示當(dāng)前時間。
- 模塊化設(shè)計:將不同的功能模塊分離,如年、月下拉框的創(chuàng)建和事件處理、日歷面板的生成、時間更新等分別封裝在不同的方法中,提高代碼的可讀性和可維護(hù)性。
- 用戶交互性:通過提供直觀的用戶界面,包括按鈕和下拉框,使用戶能夠方便地瀏覽不同的日期。同時,通過自定義的圓形標(biāo)簽突出顯示今天的日期,增強(qiáng)用戶體驗。
CalendarMain 類
整體設(shè)計目標(biāo)
CalendarMain
類的主要目標(biāo)是創(chuàng)建一個具有圖形用戶界面(GUI)的日歷應(yīng)用程序。它允許用戶查看指定月份和年份的日歷信息,能夠切換月份,并且在窗口標(biāo)題中實時顯示當(dāng)前時間。
成員變量設(shè)計思想
monthLabel
:用于直觀地向用戶展示當(dāng)前所查看日歷的月份信息。通過JLabel
來實現(xiàn),初始化為特定的月份字符串(如 "October 2023"),后續(xù)會根據(jù)用戶的操作(如切換月份)動態(tài)更新其顯示內(nèi)容。yearLabel
:與monthLabel
類似,用于顯示當(dāng)前年份。同樣是JLabel
類型,其顯示內(nèi)容會隨著用戶在年下拉框中的選擇或月份切換等操作而更新。calendarPanel
:這是整個日歷應(yīng)用程序的核心顯示區(qū)域,通過JPanel
實現(xiàn),并設(shè)置為GridLayout(7, 7)
的網(wǎng)格布局。該布局用于以一種規(guī)則的方式展示日歷中的星期標(biāo)題以及每個月的日期信息等內(nèi)容。currentMonth
和currentYear
:分別用于記錄當(dāng)前所顯示日歷的月份索引(0 - 11 分別對應(yīng)一月到十二月)和年份信息。這兩個變量在程序運(yùn)行過程中會根據(jù)用戶的操作(如切換月份、選擇年份)不斷更新,以便準(zhǔn)確顯示相應(yīng)的日歷內(nèi)容。currentTime
:用于存儲當(dāng)前時間的字符串表示。通過定時器定期更新這個變量的值,并將其用于更新窗口標(biāo)題,以實現(xiàn)實時顯示當(dāng)前時間的功能。yearComboBox
和yearComboBox
:這兩個下拉框組件分別用于用戶選擇年份和月份。yearComboBox
包含了從當(dāng)前年份前后各 20 年的年份選項,方便用戶在較大時間范圍內(nèi)選擇想要查看日歷的年份。monthComboBox
則包含了中文月份名稱數(shù)組中的各個月份名稱,使用戶能夠以更直觀的方式選擇月份。
構(gòu)造函數(shù)設(shè)計思想
- 在
CalendarMain
的構(gòu)造函數(shù)中,首先進(jìn)行了一系列窗口基本設(shè)置:- 創(chuàng)建并初始化
monthLabel
和yearLabel
,設(shè)置窗口標(biāo)題、大小以及關(guān)閉操作等,為整個應(yīng)用程序的窗口外觀和基本行為奠定基礎(chǔ)。 - 設(shè)置窗口布局為
BorderLayout
,這種布局方式便于將不同功能的組件放置在窗口的不同區(qū)域(如頂部、中央等),使得界面布局更加清晰和有條理。 - 通過獲取屏幕尺寸并計算,將窗口設(shè)置為在屏幕居中顯示,提供更好的用戶體驗。
- 創(chuàng)建并初始化
- 接著,獲取當(dāng)前時間的日歷對象,并從中提取當(dāng)前月份索引和年份信息,用于初始化
currentMonth
和currentYear
變量,確保應(yīng)用程序一開始顯示的是當(dāng)前時間對應(yīng)的日歷信息。 - 然后,分別創(chuàng)建并設(shè)置年下拉框和月下拉框:
- 對于年下拉框
yearComboBox
,通過循環(huán)添加從當(dāng)前年份前后各 20 年的年份選項,設(shè)置初始選中項為當(dāng)前年份,并為其添加動作監(jiān)聽器。當(dāng)用戶選擇不同年份時,監(jiān)聽器會觸發(fā)相應(yīng)的操作,更新currentYear
變量并重新顯示日歷內(nèi)容。 - 對于月下拉框
monthComboBox
,創(chuàng)建包含中文月份名稱的數(shù)組,并將各個月份名稱添加到下拉框中,設(shè)置初始選中項為當(dāng)前月份對應(yīng)的中文名稱。同樣為其添加動作監(jiān)聽器,當(dāng)用戶選擇不同月份時,監(jiān)聽器會觸發(fā)更新currentMonth
變量并重新顯示日歷的操作。
- 對于年下拉框
- 之后,創(chuàng)建頂部面板
topPanel
,并設(shè)置其布局為FlowLayout
,用于放置上一個月按鈕、年下拉框、月下拉框、年份標(biāo)簽以及下一個月按鈕等組件。為上一個月按鈕和下一個月按鈕分別添加動作監(jiān)聽器,點(diǎn)擊按鈕時會調(diào)用changeMonth
方法來實現(xiàn)月份的切換操作。 - 最后,創(chuàng)建用于顯示日歷內(nèi)容的
calendarPanel
,將其添加到窗口的中央?yún)^(qū)域,并調(diào)用displayCalendar
方法首次顯示日歷內(nèi)容。同時,創(chuàng)建一個定時器,每 1000 毫秒(1 秒)觸發(fā)一次updateTime
方法,用于更新窗口標(biāo)題顯示的時間。
CircleLabel 類(內(nèi)部靜態(tài)類)
整體設(shè)計目標(biāo)
CircleLabel
類是一個自定義的標(biāo)簽類,繼承自 JLabel
。其主要設(shè)計目標(biāo)是在日歷應(yīng)用程序中,針對表示當(dāng)天日期的標(biāo)簽進(jìn)行特殊繪制,使其呈現(xiàn)出圓形邊框的效果,以便用戶能夠更直觀地識別當(dāng)天日期。
成員變量設(shè)計思想
isToday
:這個布爾類型的變量用于標(biāo)記該標(biāo)簽所表示的日期是否為今天。通過這個變量,在繪制標(biāo)簽時可以根據(jù)其值來決定是否繪制紅色圓形邊框,從而實現(xiàn)對今天日期的特殊標(biāo)識。
構(gòu)造函數(shù)設(shè)計思想
- 在構(gòu)造函數(shù)
CircleLabel(String text, boolean isToday)
中:- 首先調(diào)用父類
JLabel
的構(gòu)造函數(shù),設(shè)置文本居中顯示,確保日期文本在標(biāo)簽內(nèi)的顯示效果良好。 - 然后初始化
isToday
變量,將傳入的參數(shù)值賦給它,以便后續(xù)繪制操作能夠根據(jù)這個值進(jìn)行相應(yīng)的處理。 - 最后設(shè)置標(biāo)簽的字體為
Arial
,普通樣式,字號為 20,統(tǒng)一了日期標(biāo)簽的字體格式,使整個日歷的顯示更加規(guī)范和美觀。
- 首先調(diào)用父類
paintComponent 方法設(shè)計思想
- 該方法重寫了父類
JLabel
的paintComponent
方法。 - 首先,調(diào)用父類的
paintComponent
方法進(jìn)行默認(rèn)繪制,保證標(biāo)簽的基本顯示內(nèi)容(如日期文本)能夠正常顯示。 - 然后,根據(jù)
isToday
變量的值來決定是否進(jìn)行特殊繪制:如果isToday
為true
,則將繪制圖形的上下文轉(zhuǎn)換為Graphics2D
,并設(shè)置抗鋸齒渲染提示,使繪制的圓形更平滑。接著,通過獲取標(biāo)簽的寬度和高度,計算出合適的圓形直徑以及圓心坐標(biāo),設(shè)置繪制顏色為紅色,最后繪制出紅色圓形邊框,從而實現(xiàn)了對今天日期的特殊標(biāo)識效果。
displayCalendar 方法設(shè)計思想
- 該方法的主要目的是根據(jù)當(dāng)前的
currentYear
和currentMonth
變量的值,準(zhǔn)確地在calendarPanel
上顯示相應(yīng)月份的日歷信息。 - 首先,清除
calendarPanel
上的所有組件,為重新顯示新的日歷內(nèi)容做好準(zhǔn)備。 - 然后,創(chuàng)建當(dāng)前月份的日歷對象和上一個月的日歷對象,用于獲取相關(guān)的日歷信息,如當(dāng)前月的第一天是星期幾、當(dāng)前月和上一個月的總天數(shù)等。
- 接著,更新
monthLabel
和yearLabel
的顯示內(nèi)容,使其準(zhǔn)確反映當(dāng)前所查看的月份和年份信息。 - 之后,添加星期標(biāo)題行,通過循環(huán)將星期的中文簡稱(如 “一”、“二” 等)添加到
calendarPanel
上作為日歷的標(biāo)題行。 - 再根據(jù)獲取到的當(dāng)前月的第一天是星期幾以及當(dāng)前月和上一個月的總天數(shù)等信息,分三步添加日歷中的日期信息:
- 添加上一個月的空白日期(灰色顯示):通過循環(huán),根據(jù)當(dāng)前月第一天是星期幾的信息,計算出需要添加上一個月的哪些空白日期,并將這些日期以灰色顯示的方式添加到
calendarPanel
上。 - 添加當(dāng)前月的日期:通過循環(huán)遍歷當(dāng)前月的所有日期,對于每個日期,判斷其是否為今天,如果是則使用
CircleLabel
類創(chuàng)建帶有圓形邊框標(biāo)識的標(biāo)簽,否則使用普通的JLabel
創(chuàng)建標(biāo)簽,然后將這些標(biāo)簽添加到calendarPanel
上。 - 填充后續(xù)的空白日期(灰色顯示):根據(jù)日歷布局的規(guī)則以及當(dāng)前月的總天數(shù)和第一天是星期幾等信息,計算出需要填充的后續(xù)空白日期,并將這些日期以灰色顯示的方式添加到
calendarPanel
上。
- 添加上一個月的空白日期(灰色顯示):通過循環(huán),根據(jù)當(dāng)前月第一天是星期幾的信息,計算出需要添加上一個月的哪些空白日期,并將這些日期以灰色顯示的方式添加到
- 最后,重新驗證和重繪
calendarPanel
,確保新添加的組件能夠正確顯示在窗口中,并且顯示效果良好。
changeMonth 方法設(shè)計思想
- 該方法用于實現(xiàn)月份的切換功能。當(dāng)用戶點(diǎn)擊上一個月按鈕或下一個月按鈕時,會傳入正負(fù) 1 的參數(shù)值來表示切換到上一個月或下一個月。
- 根據(jù)傳入的參數(shù)值對
currentMonth
變量進(jìn)行相應(yīng)的調(diào)整:如果currentMonth
小于 0,說明要切換到上一年的 12 月份,此時將currentMonth
設(shè)為 11,同時將currentYear
減 1;如果currentMonth
大于 11,說明要切換到下一年的 1 月份,此時將currentMonth
設(shè)為 0,同時將currentYear
增 1。 - 然后,更新年下拉框和月下拉框的選中項,使其與新的
currentYear
和currentMonth
相匹配。 - 最后,調(diào)用
displayCalendar
方法重新顯示日歷內(nèi)容,以反映出月份切換后的新情況。
main 方法設(shè)計思想
- 在
main
方法中,使用SwingUtilities.invokeLater
方法來確保在事件分發(fā)線程(EDT)中創(chuàng)建和顯示窗口。這是因為 Swing 組件必須在 EDT 中進(jìn)行創(chuàng)建和操作,以避免出現(xiàn)線程相關(guān)的問題。 - 在
invokeLater
方法內(nèi)部,創(chuàng)建了CalendarMain
類的一個實例,并設(shè)置其可見,從而啟動了整個日歷應(yīng)用程序,使得用戶可以通過圖形界面查看日歷信息、切換月份以及看到實時更新的時間顯示。
updateTime 方法設(shè)計思想
- 該方法的主要目的是更新窗口標(biāo)題顯示的時間。
- 首先,創(chuàng)建一個
SimpleDateFormat
格式器,設(shè)置其格式為 "yyyy-MM-dd HH:mm:ss",并將其時區(qū)設(shè)置為 "GMT+8"(東八區(qū),符合中國等多數(shù)地區(qū)的時間標(biāo)準(zhǔn))。 - 然后,通過調(diào)用
SimpleDateFormat
的format
方法,將當(dāng)前日期和時間(通過new java.util.Date()
獲?。└袷交癁橹付ǜ袷降淖址⑵浯鎯Φ?nbsp;currentTime
變量中。 - 最后,將窗口標(biāo)題更新為 "日歷" +
currentTime
,實現(xiàn)了在窗口標(biāo)題中實時顯示當(dāng)前時間的功能。
getMonthName 方法設(shè)計思想
- 該方法的主要目的是根據(jù)月份索引(0 - 11)獲取對應(yīng)的中文月份名稱。
- 通過創(chuàng)建一個包含中文月份名稱的數(shù)組,然后根據(jù)傳入的月份索引從數(shù)組中獲取相應(yīng)的中文月份名稱并返回,為在其他方法(如
changeMonth
方法中更新月下拉框選中項)中提供了方便的獲取中文月份名稱的方式。
設(shè)計原理
.窗口布局和組件創(chuàng)建:
- 使用JFrame作為主窗口,設(shè)置標(biāo)題、大小、關(guān)閉操作和布局。通過BorderLayout布局將窗口分為頂部和中央兩部分,頂部放置年、月下拉框和按鈕,中央放置日歷面板。
- 創(chuàng)建JLabel作為月份和年份標(biāo)簽,以及JPanel作為頂部面板和日歷面板。使用FlowLayout布局管理頂部面板,GridLayout布局管理日歷面板。
- 創(chuàng)建年、月下拉框,并添加相應(yīng)的動作監(jiān)聽器,以便在用戶選擇不同的年份和月份時更新日歷顯示。
2.日歷生成:
- 使用GregorianCalendar類獲取當(dāng)前時間和特定月份的日歷信息。通過計算當(dāng)前月的第一天是星期幾以及該月的總天數(shù),生成日歷的布局。
- 對于上一個月和下一個月的空白日期,使用灰色字體顯示上一個月的日期或下一個月的占位符。對于當(dāng)前月的日期,使用自定義的圓形標(biāo)簽突出顯示今天的日期。
3.用戶交互和時間更新:
- 為上一個月和下一個月按鈕添加動作監(jiān)聽器,實現(xiàn)月份的切換功能。在切換月份時,更新當(dāng)前月份和年份,并重新顯示日歷。
- 使用Timer類創(chuàng)建定時器,每秒鐘觸發(fā)一次時間更新操作,更新窗口標(biāo)題顯示的當(dāng)前時間。
功能實現(xiàn)
設(shè)計源碼
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 以創(chuàng)建可視化窗口 public class CalendarMain extends JFrame { // 月份標(biāo)簽,用于顯示當(dāng)前月份 private final JLabel monthLabel; // 年份標(biāo)簽,用于顯示當(dāng)前年份 private final JLabel yearLabel; // 日歷面板,用于顯示日歷內(nèi)容 private final JPanel calendarPanel; // 當(dāng)前月份的索引 private int currentMonth; // 當(dāng)前年份 private int currentYear; // 當(dāng)前時間的字符串表示 private static String currentTime; // 年下拉框組件 private JComboBox<Integer> yearComboBox; // 月下拉框組件 private JComboBox<String> monthComboBox; public CalendarMain() { // 創(chuàng)建月份標(biāo)簽,初始顯示為 "October 2023" monthLabel = new JLabel("October 2023"); // 設(shè)置窗口標(biāo)題為 "日歷" setTitle("日歷"); // 設(shè)置窗口大小為 500x450 像素 setSize(500, 450); // 設(shè)置窗口關(guān)閉操作,當(dāng)關(guān)閉窗口時退出程序 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 設(shè)置窗口布局為 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); // 獲取當(dāng)前時間的日歷對象 Calendar calendar = new GregorianCalendar(); // 獲取當(dāng)前月份的索引 currentMonth = calendar.get(Calendar.MONTH); // 獲取當(dāng)前年份 currentYear = calendar.get(Calendar.YEAR); // 創(chuàng)建年下拉框 yearComboBox = new JComboBox<>(); // 循環(huán)添加從當(dāng)前年份前后各 20 年的年份選項到年下拉框 for (int i = currentYear - 20; i <= currentYear + 20; i++) { yearComboBox.addItem(i); } // 設(shè)置年下拉框的初始選中項為當(dāng)前年份 yearComboBox.setSelectedItem(currentYear); // 為年下拉框添加動作監(jiān)聽器,當(dāng)選擇年份變化時更新當(dāng)前年份并重新顯示日歷 yearComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { currentYear = (Integer) yearComboBox.getSelectedItem(); displayCalendar(); } }); // 創(chuàng)建月下拉框 monthComboBox = new JComboBox<>(); // 創(chuàng)建包含中文月份名稱的數(shù)組 String[] monthNames = new String[]{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"}; // 循環(huán)添加中文月份名稱到月下拉框 for (int i = 0; i < 12; i++) { monthComboBox.addItem(monthNames[i]); } // 設(shè)置月下拉框的初始選中項為當(dāng)前月份對應(yīng)的中文名稱 monthComboBox.setSelectedItem(monthNames[currentMonth]); // 為月下拉框添加動作監(jiān)聽器,當(dāng)選擇月份變化時更新當(dāng)前月份并重新顯示日歷 monthComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { currentMonth = monthComboBox.getSelectedIndex(); displayCalendar(); } }); // 創(chuàng)建頂部面板,用于放置年、月下拉框和按鈕等 JPanel topPanel = new JPanel(); topPanel.setLayout(new FlowLayout()); // 創(chuàng)建上一個月按鈕,點(diǎn)擊時調(diào)用 changeMonth(-1) 方法切換到上一個月 JButton prevButton = new JButton("<"); prevButton.addActionListener(e -> changeMonth(-1)); topPanel.add(prevButton); // 將年下拉框添加到頂部面板 topPanel.add(yearComboBox); // 將月下拉框添加到頂部面板 topPanel.add(monthComboBox); // 創(chuàng)建年份標(biāo)簽(這里暫時保留原有的年份標(biāo)簽顯示方式) yearLabel = new JLabel(); topPanel.add(yearLabel); // 創(chuàng)建下一個月按鈕,點(diǎn)擊時調(diào)用 changeMonth(1) 方法切換到下一個月 JButton nextButton = new JButton(">"); nextButton.addActionListener(e -> changeMonth(1)); topPanel.add(nextButton); // 將頂部面板添加到窗口的北側(cè)(BorderLayout.NORTH) add(topPanel, BorderLayout.NORTH); // 創(chuàng)建一個 6 行 7 列的網(wǎng)格布局的面板,用于顯示日歷內(nèi)容 calendarPanel = new JPanel(new GridLayout(7, 7)); // 將日歷面板添加到窗口的中央(BorderLayout.CENTER) add(calendarPanel, BorderLayout.CENTER); // 顯示日歷內(nèi)容 displayCalendar(); // 創(chuàng)建一個定時器,每 1000 毫秒(1 秒)觸發(fā)一次更新時間的操作 Timer timer = new Timer(1000, this::updateTime); timer.start(); } // 自定義的圓形標(biāo)簽類,繼承自 JLabel private static class CircleLabel extends JLabel { // 表示是否為今天的標(biāo)志 private boolean isToday; public CircleLabel(String text, boolean isToday) { // 調(diào)用父類構(gòu)造方法,設(shè)置文本居中顯示 super(text, SwingConstants.CENTER); this.isToday = isToday; // 設(shè)置字體為 Arial,普通樣式,字號為 20 setFont(new Font("Arial", Font.PLAIN, 20)); } @Override protected void paintComponent(Graphics g) { // 調(diào)用父類的 paintComponent 方法進(jìn)行默認(rèn)繪制 super.paintComponent(g); // 如果是今天,則繪制紅色圓形 if (isToday) { Graphics2D g2d = (Graphics2D) g; // 設(shè)置抗鋸齒渲染提示,使繪制的圓形更平滑 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; // 設(shè)置繪制顏色為紅色 g2d.setColor(Color.RED); // 繪制圓形 g2d.drawOval(x, y, diameter, diameter); } } } private void displayCalendar() { // 清除日歷面板上的所有組件 calendarPanel.removeAll(); // 創(chuàng)建當(dāng)前月份的日歷對象 Calendar calendar = new GregorianCalendar(currentYear, currentMonth, 1); // 創(chuàng)建上一個月的日歷對象 Calendar prevMonth = new GregorianCalendar(); if (currentMonth == 0) { // 如果當(dāng)前月份是一月,則上一個月為去年的十二月 prevMonth.set(currentYear - 1, 11, 1); } else { // 否則,上一個月為當(dāng)前月份減一 prevMonth.set(currentYear, currentMonth - 1, 1); } // 更新月份標(biāo)簽為當(dāng)前月份的長名稱 monthLabel.setText(calendar.getDisplayName(Calendar.MONTH, Calendar.LONG, getLocale())); // 更新年份標(biāo)簽為當(dāng)前年份 yearLabel.setText(String.valueOf(currentYear)); // 添加星期標(biāo)題行 String[] days = {"一", "二", "三", "四", "五", "六", "天"}; for (String day : days) { // 創(chuàng)建星期標(biāo)題標(biāo)簽并添加到日歷面板 calendarPanel.add(new JLabel(day, SwingConstants.CENTER)); } // 獲取當(dāng)前月的第一天是星期幾(星期日為 1,星期六為 7) int startDay = calendar.get(Calendar.DAY_OF_WEEK) - 1; if (startDay == 0) startDay = 7; // 獲取當(dāng)前月的總天數(shù) int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); // 獲取上一個月的總天數(shù) int prevDaysInMonth = prevMonth.getActualMaximum(Calendar.DAY_OF_MONTH); // 獲取當(dāng)前日期的日歷對象 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); } // 添加當(dāng)前月的日期 for (int i = 1; i <= daysInMonth; i++) { boolean isToday = (i == todayDay) && (currentMonth == todayMonth) && (currentYear == todayYear); // 創(chuàng)建日期標(biāo)簽,如果是今天則用圓形標(biāo)簽顯示 calendarPanel.add(new CircleLabel(String.valueOf(i), isToday)); } // 填充后續(xù)的空白日期(灰色顯示) 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 為正負(fù) 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 確保在事件分發(fā)線程中創(chuàng)建和顯示窗口 SwingUtilities.invokeLater(() -> { CalendarMain app = new CalendarMain(); app.setVisible(true); }); } // 更新時間的方法,每秒鐘更新一次窗口標(biāo)題顯示的時間 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); } // 根據(jù)月份索引獲取中文月份名稱的方法 private String getMonthName(int monthIndex) { String[] monthNames = new String[]{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"}; return monthNames[monthIndex]; } }
總結(jié)
到此這篇關(guān)于java設(shè)計日歷可視化的文章就介紹到這了,更多相關(guān)java日歷可視化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloudStream原理和深入使用小結(jié)
Spring?Cloud?Stream是一個用于構(gòu)建與共享消息傳遞系統(tǒng)連接的高度可擴(kuò)展的事件驅(qū)動型微服務(wù)的框架,本文給大家介紹SpringCloudStream原理和深入使用,感興趣的朋友跟隨小編一起看看吧2024-06-06Java17中record替代Lombok部分功能使用場景探究
這篇文章主要介紹了使用Java17中的record替代Lombok的部分功能,本文來為大家小小的總結(jié)下,我們可以在哪些地方,利用record來替換Lombok2024-01-01jxls2.4.5如何動態(tài)導(dǎo)出excel表頭與數(shù)據(jù)
這篇文章主要介紹了jxls2.4.5如何動態(tài)導(dǎo)出excel表頭與數(shù)據(jù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Spring Boot之搞定mongoTemplate的知識小結(jié)
這篇文章主要介紹了Spring Boot之搞定mongoTemplate的知識小結(jié),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12