自定义的QGraphicsItem在覆盖鼠标事件后的不受欢迎的行为。

问题描述 投票:0回答:1

我正在尝试建立一个棋盘模型,我想让小兵GraphicsItem对象落在箱子GraphicsItem对象的中心。

我只为小兵对象实现了一个鼠标释放事件,它检查位置上的项目列表,如果有箱子存在,我就把小兵放在箱子的位置上。

现在,当我在窗口中尝试第一次移动时,它可以正常工作,但之后当我尝试移动小兵时,它又回到了原来的位置,我仍然可以移动它,但它不在鼠标光标下。

这里是代码。

import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QGridLayout,
                             QGraphicsView, QGraphicsScene, QGraphicsItem)
from PyQt5.QtGui import QPen, QBrush, QTransform
from PyQt5.QtCore import Qt, QRectF, QPointF

class Pawn(QGraphicsItem):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setPos(0, 0)
        self.setZValue(1)

        self.originalPos = self.scenePos()

    def paint(self, painter, options, widget):
        painter.setBrush(Qt.white)
        painter.drawEllipse(0, 0, 30, 30)

    def boundingRect(self):
        return QRectF(0, 0, 30, 30)

    def mouseReleaseEvent(self, event):
        dropPos = self.mapToScene(event.pos())
        dropCase = None
        for item in self.scene().items(dropPos.x(), dropPos.y(), 0.0001, 0.0001,
                                       Qt.IntersectsItemShape, 
                                       Qt.AscendingOrder):
            if isinstance(item, Case):
                dropCase = item

        if dropCase:
            newP = dropCase.scenePos()
            self.setPos(newP)
            self.originalPos = newP

        else:
            self.setPos(self.originalPos)


class Case(QGraphicsItem):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.setPos(100, 0)
        self.setZValue(0)

    def paint(self, painter, options, widget):
        painter.setPen(Qt.black)
        painter.setBrush(Qt.black)
        painter.drawRect(0, 0, 40, 40)

    def boundingRect(self):
        return QRectF(0, 0, 40, 40)

    def getCenter(self):
        x, y = self.scenePos().x() + 10, self.scenePos().y() + 10
        return QPointF(x, y)

class MainWin(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        scene = QGraphicsScene()
        view = QGraphicsView(scene, self)
        view.setGeometry(0, 0, 290, 290)

        case = Case()
        pawn = Pawn()
        scene.addItem(case)
        scene.addItem(pawn)

        self.setWindowTitle('doodling')
        self.setGeometry(200, 200, 300, 300)
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWin()
    sys.exit(app.exec_())
python pyqt pyqt5 qgraphicsscene qgraphicsitem
1个回答
0
投票

我没有实现mouseMoveEvent,因为我把它和悬停行为混淆了。

这段代码可以正常工作

from PyQt5.QtWidgets import (QApplication, QWidget, QGridLayout,
                             QGraphicsView, QGraphicsScene, QGraphicsItem)
from PyQt5.QtGui import QPen, QBrush, QTransform
from PyQt5.QtCore import Qt, QRectF, QPointF

class Pawn(QGraphicsItem):
    def __init__(self, parent = None):
        super().__init__(parent)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setPos(0, 0)
        self.setZValue(1)

        self.originalPos = self.scenePos()

    def paint(self, painter, options, widget):
        painter.setBrush(Qt.white)
        painter.drawEllipse(0, 0, 30, 30)

    def boundingRect(self):
        return QRectF(0, 0, 30, 30)

    def mouseMoveEvent(self, event):
        movePos = self.mapToScene(event.pos())
        self.setPos(movePos.x(), movePos.y())

    def mouseReleaseEvent(self, event):
        dropPos = self.mapToScene(event.pos())
        dropCase = None
        for item in self.scene().items(dropPos.x(), dropPos.y(), 0.0001, 0.0001,
                                       Qt.IntersectsItemShape, 
                                       Qt.AscendingOrder):
            if isinstance(item, Case):
                dropCase = item

        if dropCase:
            newP = dropCase.scenePos()
            self.setPos(newP)
            self.originalPos = newP
        else:
            self.setPos(self.originalPos)


class Case(QGraphicsItem):
    def __init__(self, x_coord, y_coord, parent = None):
        super().__init__(parent)
        self.setPos(x_coord, y_coord)
        self.setZValue(0)

    def paint(self, painter, options, widget):
        painter.setPen(Qt.black)
        painter.setBrush(Qt.black)
        painter.drawRect(0, 0, 40, 40)

    def boundingRect(self):
        return QRectF(0, 0, 40, 40)

    def getCenter(self):
        x, y = self.scenePos().x() + 10, self.scenePos().y() + 10
        return QPointF(x, y)

class MainWin(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        scene = QGraphicsScene()
        view = QGraphicsView(scene, self)
        view.setGeometry(0, 0, 290, 290)

        case1 = Case(-100, 0)
        case2 = Case(100, 0)
        pawn = Pawn()
        scene.addItem(case1)
        scene.addItem(case2)
        scene.addItem(pawn)

        self.setWindowTitle('doodling')
        self.setGeometry(200, 200, 300, 300)
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWin()
    sys.exit(app.exec_())
© www.soinside.com 2019 - 2024. All rights reserved.