Обновите непрозрачность QGraphicsItem - PullRequest
1 голос
/ 04 июня 2019

Я хочу обновить непрозрачность некоторых QGraphicsItem после щелчка мышью. Как следует из другого решения, QGraphicScene обновляет GraphicsItem вручную после события mouser press. Я пробовал разные setOpacity () и update () в QGraphicsScene и QGraphicsItem. Но никто не работает и не знает, что не так.

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 Ответ

1 голос
/ 04 июня 2019

Проблема в том, что когда вы перезаписываете метод рисования QGraphicsItem, вы устанавливаете постоянную непрозрачность

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