Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signals or events for QMenu tear-off

Tags:

python

pyqt

qmenu

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.

like image 662
dissidia Avatar asked Sep 13 '25 20:09

dissidia


1 Answers

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_())
like image 65
eyllanesc Avatar answered Sep 15 '25 08:09

eyllanesc