更新QGraphicsItem的不透明度

时间:2019-06-04 12:58:56

标签: python pyqt pyqt5 qgraphicsscene qgraphicsitem

我想在单击鼠标后更新某些QGraphicsItem的不透明度。根据其他解决方案的建议,在鼠标按下事件后,QGraphicScene会手动更新GraphicsItem。我在QGraphicsScene和QGraphicsItem中尝试了不同的setOpacity()和update()。但是没有一个有效,也不知道出什么问题了。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

CUBE_POS = {
    "a":(   8.281,  18.890),
    "b":(   8.668,  23.692),
    "c":(   21.493, 23.423),
    "d":(   21.24,  15.955),
    }        

class CubeItem(QGraphicsItem):

    def __init__(self, x, y, parent=None):
        super(CubeItem,self).__init__(parent)
        self.x = x
        self.y = y
        self.polygon = QPolygonF([
            QPointF(self.x-10, self.y-10), QPointF(self.x-10, self.y+10),
            QPointF(self.x+10, self.y+10), QPointF(self.x+10, self.y-10),
            ])
        self._painter = QPainter()

    ##Estimate the drawing area
    def boundingRect(self):
        return QRectF(self.x-10, self.y-10, 20, 20)

    ##Real Shape of drawing area
    def shape(self):
        path = QPainterPath()
        path.addRect(self.x-10, self.y-10, 20, 20)
        return path

    ##paint function called by graphicview
    def paint(self, painter, option, widget):
        painter.setBrush(Qt.red)
        painter.setOpacity(0.2)
        painter.drawRect(self.x-10, self.y-10, 20, 20)
        self._painter = painter

    def activate(self):
        try:
            #self._painter.setOpacity(1.0)
            self.setOpacity(1.0)
            self.update()
        except ValueError as e:
            print(e)

class TagScene(QGraphicsScene):

    def __init__(self, parent=None):
        super(TagScene, self).__init__(parent)

        self.cubes_items_ref = {}
        self.addCubes()

    def addCubes(self):
        for cube in CUBE_POS:
            newCube = CubeItem(CUBE_POS[cube][0]*15, 
                                   CUBE_POS[cube][1]*15)
            self.addItem(newCube)
            self.cubes_items_ref[cube] = newCube

    def mousePressEvent(self, event):
        print("mouse pressed")

        #for cube in self.cubes_items_ref:
        #    self.cubes_items_ref[cube].setOpacity(1.0)
        #    #self.cubes_items_ref[cube].activate()
        #self.update(QRectF(0,0,500,500))

        for cube in self.items():
            cube.setOpacity(1.0)
        self.update(QRectF(0,0,500,500))

class MainWindow(QMainWindow):

     def __init__(self):
        super(MainWindow, self).__init__()
        layout = QHBoxLayout()
        self.scene = TagScene()
        self.view = QGraphicsView(self.scene)
        self.scene.setSceneRect(QRectF(0,0,500,500))
        layout.addWidget(self.view)
        self.widget = QWidget()
        self.widget.setLayout(layout)
        self.setCentralWidget(self.widget)

if __name__ == "__main__":

    app = QApplication(sys.argv)
    test = MainWindow()
    test.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:1)

问题是,当您覆盖QGraphicsItem的paint方法时,您将设置恒定的不透明度

def paint(self, painter, option, widget):
    painter.setBrush(Qt.red)
    painter.setOpacity(0.2) # <-- this line is the problem
    painter.drawRect(self.x-10, self.y-10, 20, 20)
    self._painter = painter

而且您将不会使用QPainter已经通过paint()方法的不透明度。

如果要设置初始不透明度,则必须在构造函数中进行设置。另一方面,setOpacity()方法已经调用了update(),因此无需进行显式调用。

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

CUBE_POS = {
    "a": (8.281, 18.890),
    "b": (8.668, 23.692),
    "c": (21.493, 23.423),
    "d": (21.24, 15.955),
}


class CubeItem(QtWidgets.QGraphicsItem):
    def __init__(self, x, y, parent=None):
        super(CubeItem, self).__init__(parent)
        self.x = x
        self.y = y
        self.polygon = QtGui.QPolygonF(
            [
                QtCore.QPointF(self.x - 10, self.y - 10),
                QtCore.QPointF(self.x - 10, self.y + 10),
                QtCore.QPointF(self.x + 10, self.y + 10),
                QtCore.QPointF(self.x + 10, self.y - 10),
            ]
        )
        self.setOpacity(0.2) # initial opacity

    ##Estimate the drawing area
    def boundingRect(self):
        return QtCore.QRectF(self.x - 10, self.y - 10, 20, 20)

    ##Real Shape of drawing area
    def shape(self):
        path = QtGui.QPainterPath()
        path.addRect(self.boundingRect())
        return path

    ##paint function called by graphicview
    def paint(self, painter, option, widget):
        painter.setBrush(QtCore.Qt.red)
        painter.drawRect(self.x - 10, self.y - 10, 20, 20)


class TagScene(QtWidgets.QGraphicsScene):
    def __init__(self, parent=None):
        super(TagScene, self).__init__(parent)

        self.cubes_items_ref = {}
        self.addCubes()

    def addCubes(self):
        for cube in CUBE_POS:
            newCube = CubeItem(CUBE_POS[cube][0] * 15, CUBE_POS[cube][1] * 15)
            self.addItem(newCube)
            self.cubes_items_ref[cube] = newCube

    def mousePressEvent(self, event):
        for cube in self.items():
            cube.setOpacity(1.0) # update opacity


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        layout = QtWidgets.QHBoxLayout()
        self.scene = TagScene()
        self.view = QtWidgets.QGraphicsView(self.scene)
        self.scene.setSceneRect(QtCore.QRectF(0, 0, 500, 500))
        layout.addWidget(self.view)
        self.widget = QtWidgets.QWidget()
        self.widget.setLayout(layout)
        self.setCentralWidget(self.widget)


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    test = MainWindow()
    test.show()
    sys.exit(app.exec_())