为了账号安全,请及时绑定邮箱和手机立即绑定

QMenu 撕裂的信号或事件

QMenu 撕裂的信号或事件

千巷猫影 2022-01-05 11:37:05
是否有信号/事件我可以用于 QMenu 撕掉?我有一个QMenu子类,其中包含.setTearOffEnabled(True),但是如果用户单击撕下的“栏”,我想将此撕下设置为始终位于顶部。我无法使用QtCore.Qt.WindowStaysOnTopHint,因为这将导致我的菜单已处于撕下状态。例如:如果我的主工具区域比撕纸大,我点击我的主工具,撕纸窗口就会在它的后面。
查看完整描述

2 回答

?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

在以下代码中,当按下撕纸(虚线)时会发出 clicked 信号:


import sys

from PyQt5 import QtCore, QtWidgets



class Menu(QtWidgets.QMenu):

    clicked = QtCore.pyqtSignal()


    def mouseReleaseEvent(self, event):

        if self.isTearOffEnabled():

            tearRect = QtCore.QRect(

                0,

                0,

                self.width(),

                self.style().pixelMetric(

                    QtWidgets.QStyle.PM_MenuTearoffHeight, None, self

                ),

            )

            if tearRect.contains(event.pos()):

                self.clicked.emit()

                QtCore.QTimer.singleShot(0, self.after_clicked)

        super(Menu, self).mouseReleaseEvent(event)


    @QtCore.pyqtSlot()

    def after_clicked(self):

        tornPopup = None

        for tl in QtWidgets.QApplication.topLevelWidgets():

            if tl.metaObject().className() == "QTornOffMenu":

                tornPopup = tl

                break

        if tornPopup is not None:

            print("This is the tornPopup: ", tornPopup)

            tornPopup.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint)



if __name__ == "__main__":


    app = QtWidgets.QApplication(sys.argv)

    w = QtWidgets.QMainWindow(parent=None)

    menu = Menu("Menu", tearOffEnabled=True)

    menu.clicked.connect(lambda: print("clicked"))

    w.menuBar().addMenu(menu)

    for i in range(5):

        action = QtWidgets.QAction("action{}".format(i), w)

        menu.addAction(action)

    w.show()

    sys.exit(app.exec_())


查看完整回答
反对 回复 2022-01-05
?
慕容森

TA贡献1853条经验 获得超18个赞

当菜单被撕下时,它会被隐藏,Qt 将其替换为从 的内部子类创建的副本QMenu。因此,要WindowStaysOnTopHint在撕下的菜单上设置,您首先需要找到一种方法来获取对它的引用。一种方法是在应用程序对象上设置事件过滤器并监视正确类型的子事件:


class MenuWatcher(QtCore.QObject):

    def __init__(self, parent=None):

        super().__init__(parent)

        QtWidgets.qApp.installEventFilter(self)


    def eventFilter(self, source, event):

        if (event.type() == QtCore.QEvent.ChildAdded and

            event.child().metaObject().className() == 'QTornOffMenu'):

            event.child().setWindowFlag(QtCore.Qt.WindowStaysOnTopHint)

        return super().eventFilter(source, event)

此类将对应用程序中创建的所有撕掉的菜单进行操作。


但是,如果事件过滤是由源菜单类完成的,则可以通过比较菜单项来识别它自己的被撕掉的菜单:


class Menu(QtWidgets.QMenu):

    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        self.setTearOffEnabled(True)

        QtWidgets.qApp.installEventFilter(self)


    def eventFilter(self, source, event):

        if event.type() == QtCore.QEvent.ChildAdded:

            child = event.child()

            if (child.metaObject().className() == 'QTornOffMenu' and

                all(a is b for a, b in zip(child.actions(), self.actions()))):

                child.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint)

        return super().eventFilter(source, event)


查看完整回答
反对 回复 2022-01-05
  • 2 回答
  • 0 关注
  • 161 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信