一只萌萌小番薯
在以下代码中,当按下撕纸(虚线)时会发出 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)