QMenu 撕裂的信号或事件

是否有信号/事件我可以用于 QMenu 撕掉?

我有一个QMenu子类,其中包含.setTearOffEnabled(True),但是如果用户单击撕下的“栏”,我想将此撕下设置为始终位于顶部。

我无法使用QtCore.Qt.WindowStaysOnTopHint,因为这将导致我的菜单已处于撕下状态。

例如:如果我的主工具区域比撕纸大,我点击我的主工具,撕纸窗口就会在它的后面。


千巷猫影
浏览 162回答 2
2回答

一只萌萌小番薯

在以下代码中,当按下撕纸(虚线)时会发出 clicked 信号:import sysfrom PyQt5 import QtCore, QtWidgetsclass 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_())

慕容森

当菜单被撕下时,它会被隐藏,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)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python