如何在qgraphicsitem中启动上下文菜单事件来自qgraphicsview上下文菜单-PYQT6

发布于 2025-01-23 18:44:40 字数 375 浏览 4 评论 0原文

我在QgraphicsView上有上下文菜单。我无法激活QTEXTGRAPHICSITEM的上下文菜单。我读到我需要将场景事件发送到该项目,但是找不到使SendEvent方法起作用所需的事件。

def graphicsview_menu(self, position):
    item = self.ui.graphicsView.itemAt(position)
    if item is not None:
        self.scene.sendEvent(item, event)
        return
    # Menu for blank graphics view area
    menu = QtWidgets.QMenu()
    ...

I have a context menu on the QGraphicsView. I cannot activate the context menu of a QTextGraphicsItem. I read that I need to send a scene event to the item, but I cannot find the event needed to make the sendEvent method work.

def graphicsview_menu(self, position):
    item = self.ui.graphicsView.itemAt(position)
    if item is not None:
        self.scene.sendEvent(item, event)
        return
    # Menu for blank graphics view area
    menu = QtWidgets.QMenu()
    ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

帥小哥 2025-01-30 18:44:40

condect> contextmenupolicy文档解释说明解释说明解释说明:

此属性的默认值是qt :: DefaultContextMenu,这意味着contextmenuevent() nater被调用。 [...]使用qt :: customContextMenu,发射了信号 codycontextmenurequested()。

这意味着,如果设置自定义策略,则图形视图将 call call contextmenuevent(),这实际上允许它最终将新的图形上下文菜单事件发送到如果项目支持它。

解决方案是在 viewport 上安装事件过滤器(这是实际接收事件的内容),调用基本实现并返回event.isaccepted()的结果,它告诉该事件是否已处理(可能显示菜单的项目)。

如果未处理事件,则过滤器将返回false,这意味着将调用默认实现:该过滤器已安装在视口上,false将使它忽略了默认调用并将其转发到父级的event(视图本身),并且由于自定义策略告诉发射自定义上下文菜单信号,因此您的graphicsview_menu 实际上将调用函数:

        # somewhere in the __init__
        self.ui.graphicsView.viewport().installEventFilter(self)

    # ...

    def eventFilter(self, obj, event):
        if (obj == self.ui.graphicsView.viewport() and 
            event.type() == event.Type.ContextMenu):
                self.ui.graphicsView.contextMenuEvent(event)
                return event.isAccepted()
        return super().eventFilter(obj, event)

注意:以上显然假定主类从qwidget继承(或至少是qobject)。

As the contextMenuPolicy documentation explains:

The default value of this property is Qt::DefaultContextMenu, which means the contextMenuEvent() handler is called. [...] With Qt::CustomContextMenu, the signal customContextMenuRequested() is emitted.

This means that if you set the custom policy, the graphics view will not call contextMenuEvent(), which is what actually allows it to eventually send a new graphics context menu event to the item, if it supports it.

The solution is to install an event filter on the viewport (which is what actually receives the event in the first place), call the base implementation and return the result of the event.isAccepted(), which tells if the event was handled (an item probably showing a menu) or not.

If the event wasn't handled, then the filter will return False, which means that the default implementation would be called: the filter was installed on the viewport, False will make it ignore the default call and forward it to the event of the parent (the view itself), and since the custom policy tells to emit the custom context menu signal, your graphicsview_menu function will be actually called:

        # somewhere in the __init__
        self.ui.graphicsView.viewport().installEventFilter(self)

    # ...

    def eventFilter(self, obj, event):
        if (obj == self.ui.graphicsView.viewport() and 
            event.type() == event.Type.ContextMenu):
                self.ui.graphicsView.contextMenuEvent(event)
                return event.isAccepted()
        return super().eventFilter(obj, event)

Note: the above obviously assumes that the main class inherits from QWidget (or at least QObject).

何以心动 2025-01-30 18:44:40

谢谢。您的建议效果很好。完全理解它有点困难,但是我到了那里。如果其他任何人都有类似的问题,则已在pyqt6中发布了我的代码部分。

class ViewGraph(QDialog):
    ...
    def __init__(self):
        # Set the scene
        self.scene = GraphicsScene()  # QGraphicsScene class
        self.ui.graphicsView.setScene(self.scene)
        self.ui.graphicsView.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
        self.ui.graphicsView.customContextMenuRequested.connect(self.graphicsview_menu)
        self.ui.graphicsView.viewport().installEventFilter(self)
        # Load items into scene
        ...

def eventFilter(self, obj, event):
    """ This is required to forward context menu event to graphics view items """

    if obj == self.ui.graphicsView.viewport() and event.type() == event.Type.ContextMenu:
        self.ui.graphicsView.contextMenuEvent(event)
        return event.isAccepted()
    return super().eventFilter(obj, event)

def graphicsview_menu(self, position):
    item = self.ui.graphicsView.itemAt(position)
    if item is not None:
        # Forward contextmenu event to QTextGraphicsItem, etc
        self.scene.sendEvent(item)
        return
    # Menu for blank graphics view area
    menu = QtWidgets.QMenu()
    ...

Thank you. your suggestion works perfectly. Its a bit hard to understand it fully, but I am getting there. Have posted my code sections below in pyqt6 in case anyone else has similar issue.

class ViewGraph(QDialog):
    ...
    def __init__(self):
        # Set the scene
        self.scene = GraphicsScene()  # QGraphicsScene class
        self.ui.graphicsView.setScene(self.scene)
        self.ui.graphicsView.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
        self.ui.graphicsView.customContextMenuRequested.connect(self.graphicsview_menu)
        self.ui.graphicsView.viewport().installEventFilter(self)
        # Load items into scene
        ...

def eventFilter(self, obj, event):
    """ This is required to forward context menu event to graphics view items """

    if obj == self.ui.graphicsView.viewport() and event.type() == event.Type.ContextMenu:
        self.ui.graphicsView.contextMenuEvent(event)
        return event.isAccepted()
    return super().eventFilter(obj, event)

def graphicsview_menu(self, position):
    item = self.ui.graphicsView.itemAt(position)
    if item is not None:
        # Forward contextmenu event to QTextGraphicsItem, etc
        self.scene.sendEvent(item)
        return
    # Menu for blank graphics view area
    menu = QtWidgets.QMenu()
    ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文