带有 QGraphicsItemGroup 的事件

Posted

技术标签:

【中文标题】带有 QGraphicsItemGroup 的事件【英文标题】:Events with QGraphicsItemGroup 【发布时间】:2010-06-11 08:49:37 【问题描述】:

在我的应用程序中,我想使用 QGraphicsItemGroup 将项目分组为一个项目。 我玩了一下,不确定是否使用它,因为当我想捕捉事件时,事件会合并在一起,但我想用特定的孩子处理特定的事件。 我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

您需要致电QGraphicsItemGroup::setHandlesChildEvents(false)。这会阻止 QGraphicsItemGroup 尝试处理事件,并让子 QGraphicsItems 处理它们。

【讨论】:

【参考方案2】:

我认为这就是QGraphicsItemGroup 的意义所在。从文档来看,这是为了简化一次移动和转换多个项目,例如想象以下情况:用户在应用程序中围绕多个项目绘制一个选择矩形,因为他想移动所有项目。也许您想要更多的是创建项目的层次结构,例如有一个父项和多个子项。这样,您将获得每个项目的单独事件。这可以通过调用QGraphicsItem::setParentItem()来完成;

【讨论】:

每次我尝试使用 QGraphicsItemGroup 时,我都会回到简单的父子关系。文档不是很清楚【参考方案3】:

该问题没有具体说明所关注的 Qt 版本,并且有 Qt4 的正确答案。这是 Qt5 的答案(它适用于 PyQt5,我想它也适用于 C++)。解决方案是重新实现sceneEvent,重新实现一个专门的事件捕获器例如contextMenuEvent 是不够的。

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

from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets


class GraphicsItem(QtWidgets.QGraphicsItem):
    def __init__(self,
               rect: QtCore.QRectF,
               name: str,
               parent: QtWidgets.QGraphicsItem = None):
        super().__init__(parent)
        self._name = name
        self._rect = rect

    def boundingRect(self):
        return self._rect

    def paint(self,
              painter: QtGui.QPainter,
              option: QtWidgets.QStyleOptionGraphicsItem,
              widget: QtWidgets.QWidget = None):
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        painter.setBrush(QtGui.QBrush(QtCore.Qt.red))
        painter.drawRect(self._rect)

    def sceneEvent(self, event: QtCore.QEvent):
        if (event.type() == QtCore.QEvent.GraphicsSceneContextMenu):
            self.contextMenuEvent(event)
        event.accept()
        return True

    def contextMenuEvent(self, event: QtWidgets.QGraphicsSceneContextMenuEvent):
        print(f'contextMenuEvent in "self._name"')


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

        self._scene = QtWidgets.QGraphicsScene()

        layout = QtWidgets.QHBoxLayout()
        self._view = QtWidgets.QGraphicsView(self._scene)
        layout.addWidget(self._view)

        self._widget = QtWidgets.QWidget()
        self._widget.setLayout(layout)

        group = QtWidgets.QGraphicsItemGroup()
        self._scene.addItem(group)

        scene_item = GraphicsItem(QtCore.QRectF(0, 0, 100, 100), 'in scene')
        self._scene.addItem(scene_item)

        group_item = GraphicsItem(QtCore.QRectF(150, 0, 100, 100), 'in group')
        group.addToGroup(group_item)

        group_item = GraphicsItem(QtCore.QRectF(300, 0, 100, 100), '2nd in group')
        group.addToGroup(group_item)

        self.setCentralWidget(self._widget)
        self.setWindowTitle('contextMenuEvent with QGraphicsItemGroup')


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)

    mainWindow = MainWindow()
    mainWindow.setGeometry(100, 100, 800, 500)
    mainWindow.show()

    sys.exit(app.exec_())

【讨论】:

以上是关于带有 QGraphicsItemGroup 的事件的主要内容,如果未能解决你的问题,请参考以下文章

Qt 之 QGraphicsItemGroup

如何设置 QGraphicsItemGroup 的显示范围?

Qt 视图框架QGraphicsItem

检测 QGraphicsItemGroup 上的点击

使 QGraphicsItemGroup 的子级不可选择

QGraphicsItemGroup组合中的一些细节