出现上下文菜单时如何使小部件接收鼠标发布事件

发布于 2025-02-02 00:33:47 字数 1227 浏览 2 评论 0原文

在Ubuntu20.04上,当Windows可以接收到上下文菜单时,我无法让小部件接收鼠标发布事件。我的PYQT版本是5.15.2。

我已经考虑过手动发送鼠标发布事件,但是我不知道出现上下文菜单时哪个系统会收到鼠标发布事件,并且这样做可能会导致重复发布事件。有更好的解决方案吗?

# coding:utf-8
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMenu, QLabel


class Menu(QMenu):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.addAction('action 1')
        self.addAction('action 2')

    def showEvent(self, e):
        print('show context menu')
        super().showEvent(e)


class Widget(QLabel):

    def mousePressEvent(self, e):
        print('mouse press, button:', e.button())
        super().mousePressEvent(e)

    def mouseReleaseEvent(self, e):
        print('mouse release, button:', e.button())
        super().mouseReleaseEvent(e)


class Demo(QWidget):

    def __init__(self):
        super().__init__()
        self.widget = Widget('Click Me', self)
        self.widget.move(175, 180)
        self.resize(400, 400)

    def contextMenuEvent(self, e):
        menu = Menu(self)
        menu.exec(e.globalPos())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Demo()
    w.show()
    app.exec_()

On Ubuntu20.04, I can't have the widget receive the mouse release event when context menu appears while Windows can receive. My pyqt version is 5.15.2.

I've considered sending a mouse release event manually, but I don't know which systems will receive the mouse release event when context menu appears, and doing so may cause repeated release events. Is there any better solution?

# coding:utf-8
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMenu, QLabel


class Menu(QMenu):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.addAction('action 1')
        self.addAction('action 2')

    def showEvent(self, e):
        print('show context menu')
        super().showEvent(e)


class Widget(QLabel):

    def mousePressEvent(self, e):
        print('mouse press, button:', e.button())
        super().mousePressEvent(e)

    def mouseReleaseEvent(self, e):
        print('mouse release, button:', e.button())
        super().mouseReleaseEvent(e)


class Demo(QWidget):

    def __init__(self):
        super().__init__()
        self.widget = Widget('Click Me', self)
        self.widget.move(175, 180)
        self.resize(400, 400)

    def contextMenuEvent(self, e):
        menu = Menu(self)
        menu.exec(e.globalPos())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Demo()
    w.show()
    app.exec_()

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

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

发布评论

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

评论(1

葬心 2025-02-09 00:33:47

一般规则是,当右鼠标按钮在Windows上释放并按在Linux上时,将触发上下文菜单事件。

为了避免不一致并具有忽略OS并始终执行的通用行为,您可以在需要时设置内部标志并进行检查:由于上下文菜单事件可能会优先/em>鼠标按下和上下文菜单。

请记住:

  • 如果您不想处理上下文菜单事件并希望它传播给父母(例如在您的情况下),则事件必须忽略;如果您覆盖contextmenuevent必须使用event.ignore()或通过调用基本实现来明确完成此操作。活动;
  • 如果文本交互标志支持鼠标/键盘导航(允许剪贴板菜单),则QLABEL可能会处理事件。
  • 上下文菜单事件也可以由键盘上的菜单键触发,因此您应该确保其 原因() IS 鼠标;如果执行“ Undress”部分的功能始终检查上述标志(应该),但实际上并不需要这是不需要的,但是检查是否有完整性和一致性的原因仍然是一个很好的做法;
class Widget(QLabel):
    _isPressed = False
    def mousePressEvent(self, e):
        print('mouse press, button:', e.button())
        super().mousePressEvent(e)
        self._isPressed = True

    def mouseReleaseEvent(self, e):
        super().mouseReleaseEvent(e)
        self.unpress()

    def contextMenuEvent(self, e):
        super().contextMenuEvent(e)
        # or, alternatively:
        e.ignore()

        if e.reason() == e.Mouse:
            self.unpress()

    def unpress(self):
        if not self._isPressed:
            return
        self._isPressed = True
        # do whatever you need

The general rule is that the context menu event is fired when the right mouse buttons is released on Windows and pressed on Linux.

To avoid inconsistency and have a generic behavior that just ignores the OS and always does the same, you can set an internal flag and check it whenever is required: since the context menu event might take precedence, call a function from both mouse press and context menu.

Remember that:

  • if you don't want to handle the context menu event and want it to propagate to the parent (like in your case), the event must be ignored; if you override contextMenuEvent this must be done explicitly either with event.ignore() or by calling the base implementation, assuming that it does not accept the event;
  • QLabel might handle the event if the text interaction flag supports mouse/keyboard navigation (to allow the clipboard menu);
  • context menu event can also be triggered by the menu-key on the keyboard, so you should ensure that its reason() is Mouse; this is not actually required if the function that does the "unpress" part always check for the above flag (and it should), but it's still good practice to check for the reason for completeness and consistency;
class Widget(QLabel):
    _isPressed = False
    def mousePressEvent(self, e):
        print('mouse press, button:', e.button())
        super().mousePressEvent(e)
        self._isPressed = True

    def mouseReleaseEvent(self, e):
        super().mouseReleaseEvent(e)
        self.unpress()

    def contextMenuEvent(self, e):
        super().contextMenuEvent(e)
        # or, alternatively:
        e.ignore()

        if e.reason() == e.Mouse:
            self.unpress()

    def unpress(self):
        if not self._isPressed:
            return
        self._isPressed = True
        # do whatever you need
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文