Перестает работать смена курсора в QgraphicsView

В приведенном примере возникает проблема при переопределении методов событий мыши.

В View::QGraphicsView::mousePressEvent меняется курсор мыши, View::QGraphicsView::mouseReleaseEvent меняется на дефолтный.

В Node::QGraphicsItem::mousePressEvent меняется курсор мыши, в Node::QGraphicsItem::mouseReleaseEvent меняется на дефолтный.

Проблема:
После клика по Node перестает работать смена курсора в представлении View.

#!/usr/bin/env python3
#-*- coding: utf-8 -*-

import sys

from PySide2.QtCore import Qt, QRectF
from PySide2.QtGui import QPainterPath, QPen, QColor
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QGraphicsItem, QGraphicsView, QGraphicsScene, \
    QVBoxLayout


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setMinimumSize(300, 300)
        self.setGeometry(300, 300, 800, 600)
        self.editor = NNEditor()
        self.setCentralWidget(self.editor)


class NNEditor(QWidget):
    def __init__(self):
        super().__init__()

        self.scene = Scene()
        self.view = View(self.scene)

        self.setLayout(QVBoxLayout())
        self.layout().addWidget(self.view)

        self.node = Node()
        self.scene.addNode(self.node)


class Scene(QGraphicsScene):
    def __init__(self):
        super().__init__()

        self.colorBackground = QColor("#555555")

        self.setBackgroundBrush(self.colorBackground)
        self.sceneWidth, self.sceneHeight = 1000, 1000
        self.setSceneRect(~self.sceneWidth // 2, ~self.sceneHeight // 2,
                          self.sceneWidth, self.sceneHeight)

    def addNode(self, node):
        self.addItem(node)

    def drawBackground(self, painter, rect):
        super().drawBackground(painter, rect)


class View(QGraphicsView):
    def __init__(self, scene):
        super().__init__()

        self.setScene(scene)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.ClosedHandCursor)
        super().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.ArrowCursor)
        super().mouseReleaseEvent(event)


class Node(QGraphicsItem):
    def __init__(self):
        super().__init__()

        self.width = 180
        self.height = 240
        self.radius = 10

        self.strokeWidth = 2
        self.pen = QPen(Qt.black, self.strokeWidth)

    def boundingRect(self):
        return QRectF(0, 0, self.width + self.strokeWidth, self.height + self.strokeWidth).normalized()

    def paint(self, painter, option, widget=None):
        path_outline = QPainterPath()
        path_outline.addRoundedRect(self.strokeWidth / 2, self.strokeWidth / 2,
                                    self.width, self.height,
                                    self.radius, self.radius)

        painter.setPen(self.pen)
        painter.setBrush(Qt.NoBrush)
        painter.drawPath(path_outline.simplified())

    def shape(self):
        path_outline = QPainterPath()
        path_outline.addRoundedRect(0, 0,
                                    self.width + self.strokeWidth, self.height + self.strokeWidth,
                                    self.radius, self.radius)
        return path_outline

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.setCursor(Qt.SizeAllCursor)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.ArrowCursor)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    wnd = MainWindow()
    wnd.show()

    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

По умолчанию QGraphicsView предоставляет обычный QWidget для виджета области просмотра. Вы можете получить доступ к этому виджету, вызвав viewport(), или вы можете заменить его, вызвав setViewport().

Больше https://doc.qt.io/qt-5/qgraphicsview.html#details

import sys
'''
from PySide2.QtCore import Qt, QRectF
from PySide2.QtGui import QPainterPath, QPen, QColor
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, \
    QGraphicsItem, QGraphicsView, QGraphicsScene, QVBoxLayout
'''
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import QPainterPath, QPen, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, \
    QGraphicsItem, QGraphicsView, QGraphicsScene, QVBoxLayout


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setMinimumSize(300, 300)
        self.setGeometry(300, 300, 800, 600)
        self.editor = NNEditor()
        self.setCentralWidget(self.editor)


class NNEditor(QWidget):
    def __init__(self):
        super().__init__()

        self.scene = Scene()
        self.view = View(self.scene)

        self.setLayout(QVBoxLayout())
        self.layout().addWidget(self.view)

        self.node = Node()
        self.scene.addNode(self.node)


class Scene(QGraphicsScene):
    def __init__(self):
        super().__init__()

        self.colorBackground = QColor("#555555")

        self.setBackgroundBrush(self.colorBackground)
        self.sceneWidth, self.sceneHeight = 1000, 1000
        self.setSceneRect(~self.sceneWidth // 2, ~self.sceneHeight // 2,
                          self.sceneWidth, self.sceneHeight)

    def addNode(self, node):
        self.addItem(node)

    def drawBackground(self, painter, rect):
        super().drawBackground(painter, rect)


class View(QGraphicsView):
    def __init__(self, scene):
        super().__init__()

        self.setScene(scene)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
#            self.setCursor(Qt.ClosedHandCursor)                     # ---
            self.viewport().setCursor(Qt.ClosedHandCursor)           # +++  !!! viewport
        super().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
#            self.setCursor(Qt.ArrowCursor)                          # ---
            self.viewport().setCursor(Qt.ArrowCursor)                # +++  !!! viewport
        super().mouseReleaseEvent(event)


class Node(QGraphicsItem):
    def __init__(self):
        super().__init__()

        self.width = 180
        self.height = 240
        self.radius = 10

        self.strokeWidth = 2
        self.pen = QPen(Qt.black, self.strokeWidth)

    def boundingRect(self):
        return QRectF(0, 0, 
            self.width + self.strokeWidth, 
            self.height + self.strokeWidth
        ).normalized()

    def paint(self, painter, option, widget=None):
        path_outline = QPainterPath()
        path_outline.addRoundedRect(
            self.strokeWidth / 2, self.strokeWidth / 2,
            self.width, self.height,
            self.radius, self.radius
        )

        painter.setPen(self.pen)
        painter.setBrush(Qt.NoBrush)
        painter.drawPath(path_outline.simplified())

    def shape(self):
        path_outline = QPainterPath()
        path_outline.addRoundedRect(
            0, 0,
            self.width + self.strokeWidth, self.height + self.strokeWidth,
            self.radius, self.radius
        )
        return path_outline

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.setCursor(Qt.SizeAllCursor)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.ArrowCursor)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    wnd = MainWindow()
    wnd.show()
    sys.exit(app.exec_())
→ Ссылка