Hoy me enfrenté a una tarea aparentemente simple: en el widget de calendario en PyQt5, haga que la fecha de hoy esté rodeada por un marco verde. Pero resultó que en ruso no hay materiales sobre este tema en absoluto, y en inglés solo hay una pregunta sobre stackoverflow. Decidí hacer la vida más fácil para otros desarrolladores que recién se están familiarizando con esta biblioteca y describir cómo resolví este problema.
Crea un calendario
Para crear una ventana de calendario, abra Qt Creator o Qt Designer. En el menú lateral de la pestaña Mostrar widgets, seleccione Calendario y arrástrelo al 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)
La tarea original era hacer un recuadro verde para la fecha de hoy. Parece que basta con dibujar un rectángulo con un trazo verde. Para hacer esto, elimine la línea painter.setBrush
y establezca el color deseado en painter.setPen
. Pero si haces esto, no resulta muy agradable:
No pude encontrar una respuesta a cómo hacer los bordes del mismo grosor para este rectángulo. Pero nada le impide dibujar cuatro líneas separadas:
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())
Y el resultado final:
Qué más se puede hacer
Con la ayuda, painter
no solo puede rodear o pintar una celda, sino también escribir algo de texto o dibujar una forma geométrica. Todo depende del problema que se resuelva y de la imaginación del desarrollador.