问题
I am trying to animate a QGraphicsPixmapItem in PyQt5. The program as is crashes without any error message, and removing the lines about the variable 'anime' makes the program work normally.
here is the QGraphicsPixMapItem:
class QStone(QGraphicsPixmapItem,QGraphicsObject):
def __init__(self, color, movable):
QGraphicsPixmapItem.__init__(self)
QGraphicsObject.__init__(self)
if movable:
self.setFlag(QGraphicsItem.ItemIsMovable)
white = QPixmap("ressources/white2.png")
black = QPixmap("ressources/black_stone.png")
empty = QPixmap("ressources/no_stone.jpg")
if color == Player.white:
self.setPixmap(white.scaled(60, 60, Qt.KeepAspectRatio))
elif color == Player.black:
self.setPixmap(black.scaled(60, 60, Qt.KeepAspectRatio))
self.w = self.boundingRect().width()
self.h = self.boundingRect().height()
def hoverEnterEvent(self, event):
self.setCursor(Qt.OpenHandCursor)
self.setOpacity(0.5)
event.accept()
def hoverLeaveEvent(self, event):
self.setCursor(Qt.ArrowCursor)
self.setOpacity(1.)
event.accept()
the QGraphicsObject inheritance seems to be required for using QPropertyAnimation.
here is the code containing this animation:(this method belongs to a QGraphicsView's subclass):
def display_stone(self, x, y, color=None):
stone = ""
# if color is None:
# stone = QStone("", True)
if color == Player.white:
stone = QStone(Player.white, False)
elif color == Player.black:
stone = QStone(Player.black, False)
stone.setOpacity(0.0)
anime = QPropertyAnimation(stone, b"opacity",self)
anime.setDuration(800)
anime.setStartValue(0.0)
anime.setEndValue(1.0)
anime.start()
stone.setPos(x - stone.w / 2, y - stone.h / 2)
self.scene.addItem(stone)
stone.setZValue(10)
any idea? thank you
回答1:
Unlike the Qt C++ API, PyQt does not allow double inheritance (except in exceptional cases(1)) so you cannot implement a class that inherits from QGraphicsPixmapItem and QGraphicsObject.
In this case there are the following options:
1. In this case it is to create a QObject that handles the property you want to modify, and that is the object that is handled by the QPropertyAnimation:
class OpacityManager(QObject):
opacityChanged = pyqtSignal(float)
def __init__(self, initial_opacity, parent=None):
super(OpacityManager, self).__init__(parent)
self._opacity = initial_opacity
@pyqtProperty(float, notify=opacityChanged)
def opacity(self):
return self._opacity
@opacity.setter
def opacity(self, v):
if self._opacity != v:
self._opacity = v
self.opacityChanged.emit(self._opacity)
class QStone(QGraphicsPixmapItem):
def __init__(self, color, movable=False):
QGraphicsPixmapItem.__init__(self)
self.manager = OpacityManager(self.opacity())
self.manager.opacityChanged.connect(self.setOpacity)
if movable:
self.setFlag(QGraphicsItem.ItemIsMovable)
# ...
# ...
anime = QPropertyAnimation(stone.manager, b"opacity", stone.manager)
# ...
2. Another option is QVariantAnimation:
# ...
anime = QVariantAnimation(self)
anime.valueChanged.connect(stone.setOpacity)
anime.setDuration(800)
# ...
(1) https://www.riverbankcomputing.com/static/Docs/PyQt5/qt_interfaces.html
来源:https://stackoverflow.com/questions/57311232/animate-a-qgraphicspixmapitem