Is there a signal/event I can make use of for the QMenu tear-off?
I have a QMenu
subclass in which it has .setTearOffEnabled(True)
, but I would like to set this tear-off to always be on the top if the user clicks on the tear-off 'bar'.
I am unable to utilise QtCore.Qt.WindowStaysOnTopHint
, as this will result in my menu already being in the tear-off state.
For example: if my main tool area is bigger than the tear-off, and I click on my main tool, the tear-off window will be behind it.
In the following code the clicked signal is emitted when the tear off (dotted lines) is pressed:
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_())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With