Today I faced a seemingly simple task: in the calendar widget in PyQt5, make it so that today's date is surrounded by a green frame. But it turned out that in Russian there are no materials on this topic at all, and in English there is only one question on stackoverflow. I decided to make life easier for other developers who are just getting acquainted with this library and describe how I solved this problem.
Create a calendar
To create a calendar window, open Qt Creator or Qt Designer. In the side menu in the Display Widgets tab, select Calendar and drag it to the editor:
.ui
-. Python-, :
pyuic5 path/to/design.ui -o output/path/to/design.py
, , , , - PyQt. PATH PyQt.
design.py
, .
. , . CustomCalendar.py
, QtWidgets.QCalendarWidget
:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
class MyCalendar(QtWidgets.QCalendarWidget):
def __init__(self, parent=None):
QtWidgets.QCalendarWidget.__init__(self, parent)
:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
class MyCalendar(QtWidgets.QCalendarWidget):
def __init__(self, parent=None):
QtWidgets.QCalendarWidget.__init__(self, parent)
def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date)
if date == date.currentDate():
painter.setBrush(QtGui.QColor(0, 200, 200, 50))
painter.drawRect(rect)
printCell
:
painter
- Qt,
rect
- , ,
date
- ,
, , . -, . , , , , .
design.py
CustomCalendar
QtWidgets.QCalendarWidget
MyCalendar
:
from PyQt5 import QtCore, QtGui, QtWidgets
from CustomCalendar import MyCalendar
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(600, 502)
MainWindow.setStyleSheet("")
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.calendarWidget = MyCalendar(self.centralWidget)
self.calendarWidget.setGeometry(QtCore.QRect(60, 50, 471, 341))
self.calendarWidget.setObjectName("calendarWidget")
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 600, 22))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.mainToolBar = QtWidgets.QToolBar(MainWindow)
self.mainToolBar.setObjectName("mainToolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
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"))
, . logic.py
:
from PyQt5 import QtWidgets
import sys
import design
class CalendarApp(QtWidgets.QMainWindow, design.Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
def main():
app = QtWidgets.QApplication(sys.argv)
window = CalendarApp()
window.show()
app.exec_()
if __name__ == '__main__':
main()
, :
, paintRect
painter
, :
def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date)
if date == date.currentDate():
painter.setBrush(QtGui.QColor(0, 200, 200, 50))
painter.setPen(QtGui.QColor(0, 0, 0, 0))
painter.drawRect(rect)
The original task was to make a green box for today's date. It seems that it is enough to draw a rectangle with a green stroke. To do this, remove the line from painter.setBrush
and set the desired color to painter.setPen
. But if you do this, it turns out not very nice:
I did not find an answer to how to make the borders of the same thickness for this rectangle. But nothing prevents you from drawing four separate lines:
def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date)
if date == date.currentDate():
painter.setPen(QtGui.QPen(QtGui.QColor(0, 200, 200), 2, Qt.SolidLine, Qt.RoundCap))
painter.drawLine(rect.topRight(), rect.topLeft())
painter.drawLine(rect.topRight(), rect.bottomRight())
painter.drawLine(rect.bottomLeft(), rect.bottomRight())
painter.drawLine(rect.topLeft(), rect.bottomLeft())
And the final result:
What else can be done
With the help, painter
you can not only circle or paint a cell, but also write some text in it or draw a geometric shape. It all depends on the problem being solved and the developer's imagination.