【问题标题】:custom QGraphicsItem unwanted behaviour after overriding mouse event覆盖鼠标事件后自定义 QGraphicsItem 不需要的行为
【发布时间】:2020-09-01 07:25:23
【问题描述】:

我正在尝试为棋盘建模,我希望将棋子 GraphicsItem 对象放置在案例 GraphicsItem 对象的中心。

我只为 pawn 对象实现了一个 mouseRelease 事件,它检查该位置的项目列表,如果存在案例,我将 pawn 放在案例位置。

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

代码如下:

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】:

    我没有实现 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_())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 2011-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多