简体   繁体   中英

How to change the background colour of a cell in a QCalendarWidget using an SQL database

This is not duplicate question of How to Output sql data onto a QCalendarWidget

This is an addon of that question.

This also isn't a duplicate of Highlight date interval in a Qt5 Calendar Widget as this is just highlighting cells when the user selects it on the actual QT page and not by using SQL data. It also isn't a duplicate question of Coloring PyQt5 QCalendarWidget cell and printing data inside the cells as the answer doesnt do what i want my program to do which is to change the background Colour of a particular cell of the calendar using my sql database to do this, as well as i couldnt get the answer to work.

In the first linked question i was asking how a user would press a date and it would output the text corresponding to that date if that date was in a sql database. With some help I managed to get this working. Now what i want to do is highlight those dates with a blue background like how the current date is highlighted by a red background.

My QT page i have made is this:

My QT Page

My Database is this:

My database

And my code is this:

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

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


from PyQt5 import QtCore, QtGui, QtWidgets
import sqlite3
import datetime
import PyQt5
from PyQt5.QtCore import QDate, Qt
from PyQt5.QtGui import (QColor, QFont, QTextCharFormat, QTextLength,
        QTextTableFormat)
from PyQt5.QtWidgets import (QApplication, QComboBox, QDateTimeEdit,
        QHBoxLayout, QLabel, QMainWindow, QSpinBox, QTextBrowser, QVBoxLayout,
        QWidget)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1200, 900)
        MainWindow.setMinimumSize(QtCore.QSize(0, 0))
        MainWindow.setMaximumSize(QtCore.QSize(1200, 900))
        MainWindow.setStyleSheet("background-color: rgb(200, 200, 200);")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.Header = QtWidgets.QTextEdit(self.centralwidget)
        self.Header.setEnabled(False)
        self.Header.setGeometry(QtCore.QRect(-10, 0, 1300, 110))
        self.Header.setMinimumSize(QtCore.QSize(1300, 110))
        self.Header.setMaximumSize(QtCore.QSize(1300, 110))
        self.Header.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"border-color: rgb(255, 255, 255);\n"
"border-width : 1.2px;\n"
"border-style:inset;")
        self.Header.setObjectName("Header")
        self.LECTURP = QtWidgets.QLabel(self.centralwidget)
        self.LECTURP.setGeometry(QtCore.QRect(512, 2, 180, 61))
        self.LECTURP.setStyleSheet("color: rgb(0, 176, 240);\n"
"font: 8pt \"MS Shell Dlg 2\";\n"
"text-decoration: underline;\n"
"background-color: rgb(255, 255, 255);\n"
"font: 28pt \"Calbri\";\n"
"text-decoration: underline;")
        self.LECTURP.setObjectName("LECTURP")
        self.LecturpBanner = QtWidgets.QLabel(self.centralwidget)
        self.LecturpBanner.setGeometry(QtCore.QRect(320, 60, 561, 31))
        self.LecturpBanner.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"color: rgb(0, 176, 240);\n"
"font: 14pt \"Calibri\";")
        self.LecturpBanner.setObjectName("LecturpBanner")
        self.calendarWidget = QtWidgets.QCalendarWidget(self.centralwidget)
        self.calendarWidget.setGeometry(QtCore.QRect(30, 110, 1141, 661))
        self.calendarWidget.setStyleSheet("alternate-background-color: rgb(255, 255, 255);\n"
"font: 75 16pt \"MS Shell Dlg 2\";\n"
"background-color: rgb(200, 200, 200);\n"
"selection-background-color: rgb(255, 0, 0);")
        self.calendarWidget.setObjectName("calendarWidget")
        self.DateInfoOutput = QtWidgets.QLabel(self.centralwidget)
        self.DateInfoOutput.setGeometry(QtCore.QRect(30, 778, 1141, 97))
        self.DateInfoOutput.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"border-color: rgb(0, 0, 0);\n"
"font: 16pt \"Calibri\";\n"
"border-width : 1.2px;\n"
"border-style:inset;")
        self.DateInfoOutput.setText("")
        self.DateInfoOutput.setObjectName("DateInfoOutput")
        self.WeekNumber = QtWidgets.QLabel(self.centralwidget)
        self.WeekNumber.setGeometry(QtCore.QRect(56, 168, 113, 49))
        self.WeekNumber.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"font: 16pt \"MS Shell Dlg 2\";")
        self.WeekNumber.setObjectName("WeekNumber")
        self.calendarWidget.raise_()
        self.Header.raise_()
        self.LECTURP.raise_()
        self.LecturpBanner.raise_()
        self.DateInfoOutput.raise_()
        self.WeekNumber.raise_()
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

        self.editor = QTextBrowser()


        self.calendarWidget.clicked[QDate].connect(self.dateClicked)


    def dateClicked(self, clickedDate):
        connection = sqlite3.connect("Calendardatabase.db") 
        crsr = connection.cursor() 
        crsr.execute(
            'SELECT Text FROM Calendar WHERE Day = ? AND Month = ? AND YEAR = ?', 
            (clickedDate.day(), clickedDate.month(), clickedDate.year()))
        result = crsr.fetchone()

        if result:
            self.DateInfoOutput.setText(result[0])
        else:
            self.DateInfoOutput.setText('')


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.LECTURP.setText(_translate("MainWindow", "LECTURP"))
        self.LecturpBanner.setText(_translate("MainWindow", "Lecture, Exam, Coursework, Timetable, Uploader and Reminder Program."))
        self.WeekNumber.setText(_translate("MainWindow", "Week No."))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Ive tried to follow your comments and i have done this:

    crsr.execute('SELECT Date FROM Calendar2 WHERE Number = ?', (Count,))
        Dates3 = crsr.fetchone()
        Dates3 = str(Dates3)
        Dates3 = Dates3.replace("'", "")
        Dates3 = Dates3.replace('(', '')
        Dates3 = Dates3.replace(')', '')
        Dates3 = Dates3.replace(',', '')
        print(All_Dates)

        print(Dates3)
        Dates3 = Dates3.replace('/', ',')


        self.dates = { QDate(2020, 3, 20): ["Um Sure"] }

        format = QTextCharFormat() 
        format.setBackground(QColor("salmon")) 
        self.calendarWidget.setDateTextFormat(Dates3, format)

whever i try to run this i get this error:

Message=setDateTextFormat(self, Union[QDate, datetime.date], QTextCharFormat): argument 1 has unexpected type 'str'

I've tried to use the self.dates variable but that also didn't work. I'm not sure how to convert the date into a format thats acceptable for the QDate part of the output.

Ok everything works but when i made this while loop i was just wondering if im doing wrong python or wrong QT.

    Count = 1 
        while Count <= list3:
            connection = sqlite3.connect("Calendardatabase.db") 
            # This is the code for the database cursor 


            Current_Day = datetime.date.today().strftime("%A,")
            Current_Date = datetime.date.today().strftime("%d")
            Current_Month = datetime.date.today().strftime("%B")


            Combined_Date = ("It is a " + Current_Day + " It is the " + Current_Date + " of " + Current_Month)

            Combined_Date = str(Combined_Date)

            self.DateInfoOutput.setText(Combined_Date)

            cursor = self.editor.textCursor()



            crsr.execute('SELECT Date FROM Calendar2 WHERE Number = ?', (Count,))
            Dates3 = crsr.fetchone()
            Dates3 = str(Dates3)
            Dates3 = Dates3.replace("'", "")
            Dates3 = Dates3.replace('(', '')
            Dates3 = Dates3.replace(')', '')
            Dates3 = Dates3.replace(',', '')


            crsr.execute('SELECT Text FROM Calendar2 WHERE Number = ?', (Count,))
            Text = crsr.fetchone()
            Text = str(Text)
            Text = Text.replace("'", "")
            Text = Text.replace('(', '')
            Text = Text.replace(')', '')
            Text = Text.replace(',', '')


            print(Dates3)

            Dates3 = Dates3.replace('/', ' ')
            Dates3 = Dates3.replace("'", '')
            Dates3.split()

            sqlDay = int(Dates3[0:2])
            sqlMonth = int(Dates3[3:4])
            sqlYear = int(Dates3[6:10])



            self.dates = { QDate(sqlYear, sqlMonth, sqlDay): ["Hi"]}



            format = QTextCharFormat() 
            format.setBackground(QColor("lightblue")) 


            Count = Count + 1
            for date, value in self.dates.items(): 
                self.calendarWidget.setDateTextFormat(date, format)
                self.DateInfoOutput.setText(Text)
            else:
                self.DateInfoOutput.setText(Combined_Date)
        else:
            self.DateInfoOutput.setText(Combined_Date)

The procedure for this case is:

import os
import sqlite3

from PyQt5 import QtCore, QtGui, QtWidgets

CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    calendar = QtWidgets.QCalendarWidget()
    calendar.show()

    connection = sqlite3.connect(os.path.join(CURRENT_DIR, "Calendardatabase.db"))
    crsr = connection.cursor()
    crsr.execute("""SELECT Date FROM Calendar2""")

    date_format = "d/M/yyyy"
    cell_format = QtGui.QTextCharFormat()
    cell_format.setBackground(QtGui.QColor("red"))

    for row in crsr.fetchall():
        date_str, *_ = row
        dt = QtCore.QDate.fromString(date_str, date_format)
        if dt.isValid():
            calendar.setDateTextFormat(dt, cell_format)
        else:
            print("{} does not match format {}".format(date_str, date_format))

    sys.exit(app.exec_())

After getting help from @eyllanesc i have fully completed my program and i'm going to leave my program here so that if anyone gets stuck they can use my program as a guide or just help in any case.

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

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


from PyQt5 import QtCore, QtGui, QtWidgets
import sqlite3
import datetime
import PyQt5
from PyQt5.QtCore import QDate, Qt
from PyQt5.QtGui import (QColor, QFont, QTextCharFormat, QTextLength,
        QTextTableFormat)
from PyQt5.QtWidgets import (QApplication, QComboBox, QDateTimeEdit,
        QHBoxLayout, QLabel, QMainWindow, QSpinBox, QTextBrowser, QVBoxLayout,
        QWidget)

class Ui_CalendarWidget(object):
    def setupUi(self, CalendarWidget):
        CalendarWidget.setObjectName("CalendarWidget")
        CalendarWidget.resize(1200, 900)
        CalendarWidget.setMinimumSize(QtCore.QSize(0, 0))
        CalendarWidget.setMaximumSize(QtCore.QSize(1200, 900))
        CalendarWidget.setStyleSheet("background-color: rgb(200, 200, 200);")
        self.centralWidget = QtWidgets.QWidget(CalendarWidget)
        self.centralWidget.setObjectName("centralWidget")
        self.Header = QtWidgets.QTextEdit(self.centralWidget)
        self.Header.setEnabled(False)
        self.Header.setGeometry(QtCore.QRect(-10, 0, 1300, 110))
        self.Header.setMinimumSize(QtCore.QSize(1300, 110))
        self.Header.setMaximumSize(QtCore.QSize(1300, 110))
        self.Header.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"border-color: rgb(255, 255, 255);\n"
"border-width : 1.2px;\n"
"border-style:inset;")
        self.Header.setObjectName("Header")
        self.LECTURP = QtWidgets.QLabel(self.centralWidget)
        self.LECTURP.setGeometry(QtCore.QRect(512, 2, 180, 61))
        self.LECTURP.setStyleSheet("color: rgb(0, 176, 240);\n"
"font: 8pt \"MS Shell Dlg 2\";\n"
"text-decoration: underline;\n"
"background-color: rgb(255, 255, 255);\n"
"font: 28pt \"Calbri\";\n"
"text-decoration: underline;")
        self.LECTURP.setObjectName("LECTURP")
        self.LecturpBanner = QtWidgets.QLabel(self.centralWidget)
        self.LecturpBanner.setGeometry(QtCore.QRect(320, 60, 561, 31))
        self.LecturpBanner.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"color: rgb(0, 176, 240);\n"
"font: 14pt \"Calibri\";")
        self.LecturpBanner.setObjectName("LecturpBanner")
        self.calendarWidget = QtWidgets.QCalendarWidget(self.centralWidget)
        self.calendarWidget.setGeometry(QtCore.QRect(30, 110, 1141, 661))
        self.calendarWidget.setStyleSheet("alternate-background-color: rgb(255, 255, 255);\n"
"font: 75 16pt \"MS Shell Dlg 2\";\n"
"background-color: rgb(200, 200, 200);\n"
"selection-background-color: rgb(255, 0, 0);")
        self.calendarWidget.setObjectName("calendarWidget")
        self.DateInfoOutput = QtWidgets.QLabel(self.centralWidget)
        self.DateInfoOutput.setGeometry(QtCore.QRect(30, 778, 1141, 97))
        self.DateInfoOutput.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"border-color: rgb(0, 0, 0);\n"
"font: 16pt \"Calibri\";\n"
"border-width : 1.2px;\n"
"border-style:inset;")
        self.DateInfoOutput.setText("")
        self.DateInfoOutput.setObjectName("DateInfoOutput")
        self.WeekNumber = QtWidgets.QLabel(self.centralWidget)
        self.WeekNumber.setGeometry(QtCore.QRect(56, 168, 113, 49))
        self.WeekNumber.setStyleSheet("background-color: rgb(255, 255, 255);\n"
"font: 16pt \"MS Shell Dlg 2\";")
        self.WeekNumber.setObjectName("WeekNumber")
        self.calendarWidget.raise_()
        self.Header.raise_()
        self.LECTURP.raise_()
        self.LecturpBanner.raise_()
        self.DateInfoOutput.raise_()
        self.WeekNumber.raise_()
        CalendarWidget.setCentralWidget(self.centralWidget)
        self.statusbar = QtWidgets.QStatusBar(CalendarWidget)
        self.statusbar.setObjectName("statusbar")
        CalendarWidget.setStatusBar(self.statusbar)

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

        self.editor = QTextBrowser()


        self.calendarWidget.clicked[QDate].connect(self.dateClicked)

        connection = sqlite3.connect("Calendardatabase.db")
        crsr = connection.cursor()

        Current_Day = datetime.date.today().strftime("%A,")
        Current_Date = datetime.date.today().strftime("%d")
        Current_Month = datetime.date.today().strftime("%B")

        Combined_Date = ("It is a " + Current_Day + " It is the " + Current_Date + " of " + Current_Month)

        Combined_Date = str(Combined_Date)

        self.DateInfoOutput.setText(Combined_Date)


        #This is where the SQL Data is converted to d/M/yyyy and is then highlighted onto the calendar widget itself.

        connection = sqlite3.connect("Calendardatabase.db")
        crsr = connection.cursor()
        crsr.execute("""SELECT Date FROM Calendar2""")

        date_format = "d/M/yyyy"
        cell_format = QtGui.QTextCharFormat()
        cell_format.setBackground(QtGui.QColor("lightblue"))

        for row in crsr.fetchall():
            date_str, *_ = row
            dt = QtCore.QDate.fromString(date_str, date_format)
            if dt.isValid():
                self.calendarWidget.setDateTextFormat(dt, cell_format)
            else:
                self.DateInfoOutput.setText("{} does not match format {}".format(date_str, date_format))









    def dateClicked(self, clickedDate):
        connection = sqlite3.connect("Calendardatabase.db") 
        # This is the code for the database cursor 
        crsr = connection.cursor() 
        Count = 1
        crsr.execute('SELECT Day FROM Calendar WHERE Number = ?', (Count,))
        RawDay = crsr.fetchone()
        Day = str(RawDay)
        Day = Day.replace('(', '')
        Day = Day.replace(')', '')
        Day = Day.replace(',', '')
        Day = int(Day)

        crsr.execute('SELECT Month FROM Calendar WHERE Number = ?', (Count,))
        RawMonth = crsr.fetchone()
        Month = str(RawMonth)
        Month = Month.replace('(', '')
        Month = Month.replace(')', '')
        Month = Month.replace(',', '')
        Month = int(Month)

        crsr.execute('SELECT Year FROM Calendar WHERE Number = ?', (Count,))
        RawYear = crsr.fetchone()
        Year = str(RawDay)
        Year = Year.replace('(', '')
        Year = Year.replace(')', '')
        Year = Year.replace(',', '')
        Year = int(Year)        


        Current_Day = datetime.date.today().strftime("%A,")
        Current_Date = datetime.date.today().strftime("%d")
        Current_Month = datetime.date.today().strftime("%B")


        Combined_Date = ("It is a " + Current_Day + " It is the " + Current_Date + " of " + Current_Month)

        Combined_Date = str(Combined_Date)

        self.DateInfoOutput.setText(Combined_Date)

        cursor = self.editor.textCursor()

        All_Dates = (Day, Month, Year)

        self.selectedDate = QDate.currentDate()
        connection = sqlite3.connect("Calendardatabase.db") 
        crsr = connection.cursor() 
        crsr.execute(
            'SELECT Text FROM Calendar WHERE Day = ? AND Month = ? AND YEAR = ?', 
            (clickedDate.day(), clickedDate.month(), clickedDate.year()))
        result = crsr.fetchone()

        self.Date = (clickedDate.day() , '/' , clickedDate.month() , '/' , clickedDate.year())



        if result:
            self.DateInfoOutput.setText(result[0])


        else:
            self.DateInfoOutput.setText(Combined_Date)








    def retranslateUi(self, CalendarWidget):
        _translate = QtCore.QCoreApplication.translate
        CalendarWidget.setWindowTitle(_translate("CalendarWidget", "CalendarWidget"))
        self.LECTURP.setText(_translate("CalendarWidget", "LECTURP"))
        self.LecturpBanner.setText(_translate("CalendarWidget", "Lecture, Exam, Coursework, Timetable, Uploader and Reminder Program."))
        self.WeekNumber.setText(_translate("CalendarWidget", "Week No."))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    CalendarWidget = QtWidgets.QMainWindow()
    ui = Ui_CalendarWidget()
    ui.setupUi(CalendarWidget)
    CalendarWidget.show()
    sys.exit(app.exec_())

To get this program to work you will also need my database and you can get that from here: https://www.dropbox.com/s/cua9gypkl869hnm/Calendardatabase.db?dl=0 If you just put this in the same folder as the program file this should work.

Thank you for all the help @eyllanesc i would've been stuck for weeks on this problem withhout your help :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM