Personalización del calendario PyQt5

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.








All Articles