Skip to content

[PyQt5] 基本教學(9) QCalendar,使用 Python 輕鬆創造日曆元件

Last Updated on 2021-04-11 by Clay

本來想快速帶過 PyQt5 的基本教學,但奈何事與願違。自從開始學習、替很多程式加上圖形化界面後,越是發現自己需要學習、紀錄的東西還有很多。

日曆元件便是撰寫程式很常使用的一個元件。所幸,在 PyQt5 當中有個著可以呼叫的日曆元件,也可以實現一定程度的客製化。那麼,我今天就來紀錄一下我使用的心得。


Getting Start

首先,先來看看要如何實現最重要的功能 —— 使用者選取日期,然後我們電腦可以將使用者選取的日期選取起來。

附上我的界面程式(使用 PyUIC 轉換產生):

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'calendar_test.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.calendarWidget = QtWidgets.QCalendarWidget(self.centralwidget)
        self.calendarWidget.setGeometry(QtCore.QRect(0, 0, 661, 431))
        self.calendarWidget.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
        self.calendarWidget.setObjectName("calendarWidget")
        self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget)
        self.lcdNumber.setGeometry(QtCore.QRect(0, 440, 661, 111))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(6)
        font.setBold(True)
        font.setWeight(75)
        self.lcdNumber.setFont(font)
        self.lcdNumber.setDigitCount(15)
        self.lcdNumber.setProperty("value", 777777777.0)
        self.lcdNumber.setProperty("intValue", 777777777)
        self.lcdNumber.setObjectName("lcdNumber")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 25))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


雖然提這個有點突然,但一開始 lcdNumber 這個元件的初始值為 777777777 這個是我的惡趣味,可以隨便設一個數字,設 0 也可以。

# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
from calendar_test import Ui_MainWindow
import sys

monthConvert = {'一': '01', '二': '02', '三': '03', '四': '04', '五': '05', '六': '06', '七': '07', '八': '08',
                '九': '09', '十': '10', '十一': '11', '十二': '12'}


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle('Calendar')

        # Calender
        self.ui.calendarWidget.selectionChanged.connect(self.calendarEvent)

    def calendarEvent(self):
        date = self.ui.calendarWidget.selectedDate().toString().split(' ')
        weekday, month, day, year = date
        print(date)
        month = monthConvert[month[0]]
        self.ui.lcdNumber.display('%s %s %s' % (year, month, day))


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


這裡是我寫元件功能的部份。顯示的界面如下:

預設會直接選擇當天的日期。

最重要的部份如下:

self.ui.calendarWidget.selectionChanged.connect(self.calenderEvent)


calendarWidget 是我們的日曆元件,我們在這裡設定當使用者選擇日期時,連接我們另外寫的事件 self.calendarEvent。

def calendarEvent(self):
    date = self.ui.calendarWidget.selectedDate().toString().split(' ')
    weekday, month, day, year = date
    print(date)
    month = monthConvert[month[0]]
    self.ui.lcdNumber.display('%s %s %s' % (year, month, day))


這就是我們觸發的事件 calendarEvent()

我們將 selectedDate().toString() 得到的日期分別存入 weekday, month, day, year 四個變數裡頭。(禮拜幾其實並沒有用到。)

然後將 month 轉換成數字。(因為我系統語言是中文,而中文沒辦法顯示在 LCD 元件上,所以轉換一下)

然後,將我們選擇的日期顯示在 LCD 元件上。

像我選擇了 2019 年 10 月 27 日,下方的 LCD 馬上顯示出數字。

另外,也可以客製化這個元件,讓這個元件顯得酷一點、時尚一點:

就像這樣 XD


Read More

Leave a Reply