【问题标题】:Signaling from one QGraphicsItem in a list to all items in that list从列表中的一个 QGraphicsItem 向该列表中的所有项目发送信号
【发布时间】:2018-07-02 05:27:07
【问题描述】:

背景:我正在尝试制作一个日历应用程序。我通过为给定月份中的每个日期安排 QGraphicsItemGroup 元素来创建月份的自定义视图。所有 QGraphicsItemGroup 元素都在一个列表中以便于迭代。当鼠标悬停在日期上时,背景变为灰色。单击日期时,背景变为蓝色。当点击另一个日期时,它会被标记为蓝色,并且之前的日期会被清除。

月份概览

问题:我只希望最后一次点击的日期有蓝色背景,而不是所有点击的日期。所有其他日期元素都应具有白色背景。我不知道如何从日期列表中的一个 QGraphicsItemGroup 元素向该列表中的所有元素发送信号。

当前代码:

# 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_()

可能的解决方案:

  1. 在 CalendarList 类中创建一个可由 DateElement 引发的信号,然后触发 CalendarList 中所有项目的 clearBackground 方法。

【问题讨论】:

    标签: python pyqt pyqt4 qgraphicsview qgraphicsitem


    【解决方案1】:

    CalendarList不是继承自QObject的类所以它不支持信号,我的回答是通过scene().items()获取项目的意义,那么我们只是过滤DateElement的项目类并具有真实状态,则将使用clearRectangle() 方法:

    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()
    

    【讨论】:

    • 谢谢!您的解决方案效果很好。您的代码中有一个小错误。它的 self.scene.items() 没有场景后的 ()。
    • @Kingmaker 在我的 PyQt4 版本中有 scene() 方法,也许你的是旧版本,如果我的回答对你有帮助,不要忘记将其标记为正确,如果你不知道如何查看tour:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多