Background: I am attempting to make a calendar app. I´m creating a custom view of the month by arranging QGraphicsItemGroup elements for each date in the given month.All QGraphicsItemGroup elements are in a list for easy iteration. While the mouse hovers over a date, the background changes to grey. When a date is clicked, the background changes to blue. When another date is clicked it is marked blue and the previous date is cleared.
Month overview
Question: I just want the last clicked date to have a blue background, not all clicked dates. All the other date elements should have a white background. I can´t figure out how to send a signal from one QGraphicsItemGroup element in the date list to all elements in that list.
Current Code:
# coding=utf-8
from PyQt4.QtCore import Qt
import sys
from datetime import *
from calendar import Calendar
from PyQt4.QtGui import (QApplication, QDialog, QGraphicsView, QGraphicsScene, QGraphicsRectItem, QVBoxLayout,
QGraphicsSimpleTextItem, QBrush, QFont, QGraphicsItemGroup)
class GraficsView(QDialog):
def __init__(self, parent=None):
monthnames = ("Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "November",
"Dezember")
super(GraficsView, self).__init__(parent)
self.viewbox = QGraphicsView()
layout = QVBoxLayout()
layout.addWidget(self.viewbox)
self.setLayout(layout)
self.scene = QGraphicsScene(self.viewbox)
self.scene.setSceneRect(0,0,701,501)
self.calendarList = CalendarList(datetime(2018,2,1), self.scene)
self.viewbox.setScene(self.scene)
class DateElement(QGraphicsItemGroup):
def __init__(self, scene, status=False, date=datetime.today(), coordinates=()):
QGraphicsItemGroup.__init__(self, scene=scene)
wochentage = ("Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag")
self.status = status
if self.status:
self.setdate(date)
self.setcoordinates(coordinates)
def setdate(self, date):
wochentage = ("Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag")
self.date = date
self.dayname = wochentage[self.date.weekday()]
self.daynumber = self.date.day
def setcoordinates(self, coordinates):
self.coordinates = coordinates
self.rectangle = QGraphicsRectItem(self.coordinates[0], self.coordinates[1], self.coordinates[2],
self.coordinates[3])
self.rectangle.setAcceptHoverEvents(True)
self.fontA = QFont("Verdana", 10, QFont.Bold)
self.fontB = QFont("Verdana", 18, QFont.Bold)
self.lableday = QGraphicsSimpleTextItem()
if self.dayname in ("Samstag", "Sonntag"):
self.lableday.setBrush(QBrush(Qt.red))
else:
self.lableday.setBrush(QBrush(Qt.black))
self.lableday.setFont(self.fontA)
self.lableday.setText(self.dayname)
self.lableday.setPos(self.coordinates[0]+3, self.coordinates[1])
self.lablenumber = QGraphicsSimpleTextItem()
if self.dayname in ("Samstag", "Sonntag"):
self.lablenumber.setBrush(QBrush(Qt.red))
else:
self.lablenumber.setBrush(QBrush(Qt.black))
self.lablenumber.setFont(self.fontB)
self.lablenumber.setText(str(self.daynumber)+".")
self.lablenumber.setPos(self.coordinates[0]+3, self.coordinates[1]+12)
self.addToGroup(self.rectangle)
self.addToGroup(self.lableday)
self.addToGroup(self.lablenumber)
def hoverEnterEvent(self, event):
self.rectangle.setBrush(QBrush(Qt.lightGray))
self.update()
def hoverLeaveEvent(self, event):
self.rectangle.setBrush(QBrush(Qt.white))
self.update()
def mousePressEvent(self, event):
self.rectangle.setAcceptHoverEvents(False)
self.rectangle.setBrush(QBrush(Qt.blue))
self.update()
def clearRectangle(self):
self.rectangle.setAcceptHoverEvents(True)
self.rectangle.setBrush(QBrush(Qt.white))
self.update()
class CalendarList():
def __init__(self, date, scene):
self.date = date
self.scene = scene
self.dateelements = []
self.createdates()
def createdates(self):
weekcount = 0
daycount = 0
calendarobjekt = Calendar()
for dateobjekt in calendarobjekt.itermonthdates(self.date.year, self.date.month):
if daycount < 7:
if dateobjekt.month == self.date.month:
self.dateelements.append(DateElement(self.scene, True, dateobjekt, (daycount*100, weekcount*100, 100, 100)))
else:
self.dateelements.append(DateElement(self.scene))
daycount += 1
else:
daycount = 0
weekcount += 1
if dateobjekt.month == self.date.month:
self.dateelements.append(DateElement(self.scene, True, dateobjekt, (daycount*100, weekcount*100, 100, 100)))
else:
self.dateelements.append(DateElement(self.scene))
daycount += 1
app = QApplication(sys.argv)
form = GraficsView()
form.show()
app.exec_()
Possible Solutions:
CalendarList
is not a class that inherits from QObject
so it does not support the signals, my answer goes in the sense of obtaining the items through scene().items()
, then we just filter the items of the DateElement
class and have a true status, then the clearRectangle()
method will be used:
def mousePressEvent(self, event):
for item in self.scene().items():
if isinstance(item, DateElement):
if item.status:
item.clearRectangle()
self.rectangle.setAcceptHoverEvents(False)
self.rectangle.setBrush(QBrush(Qt.blue))
#self.update()