Reputation: 38
I am building a GUI in python with PyQt5 and I need that when I right-click on an option in my context menu, it displays another context menu as in the image...
(I am aware that I can nest a menu in one of the options, but that is not what I am looking for)
The context menu does not distinguish between right-click and left-click.
There are two problems that I see to achive this...
PyQt5.QtWidgets.QAction
..installEventFilter()
method on a widget, but in this case, you should use it on an object of type PyQt5.QtWidgets.QAction
I know that what I am asking is something complex to achieve, but I would greatly appreciate it if you could give me some information to help me achieve it.
Here I leave you the code of a GUI with a widget with a contextual menu installed on it...
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu
import sys
from PyQt5.QtCore import QEvent
class MyWindow(QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.createWidgets()
def createWidgets(self):
self.my_button = QtWidgets.QPushButton(self)
self.my_button.setText("My Widget")
self.my_button.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.ContextMenu and source is self.my_button:
menu = QMenu()
action1 = menu.addAction("Option 1")
action2 = menu.addAction("Option 2")
action3 = menu.addAction("Option 3")
selected_action = menu.exec_(event.globalPos())
if selected_action == action1:
print("You have selected the first option")
if selected_action == action2:
print("You have selected the second option")
if selected_action == action3:
print("You have selected the third option")
return super().eventFilter(source, event)
def showWindow():
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
showWindow()
Upvotes: 1
Views: 3414
Reputation: 48479
It is not enough to install the event filter on the button, and you certainly cannot install it on the QAction, which will never trigger mouse events since it does not inherit from QWidget. You have to install the filter on the menu itself.
In order to allow correct tracking of menus (and properly react to their events), it's also better to keep more static references to the menus too.
Obviuosly, you could create a subclass of QMenu, which will probably make things easier.
class MyWindow(QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.createWidgets()
def createWidgets(self):
self.my_button = QtWidgets.QPushButton(self)
self.my_button.setText("My Widget")
self.buttonMenu = QMenu(self.my_button)
self.buttonMenu.addAction("Option 1")
self.buttonMenu.addAction("Option 2")
self.buttonMenu.addAction("Option 3")
self.subMenu = QMenu(self.buttonMenu)
self.subMenu.addAction("Sub Option 1")
self.subMenu.addAction("Sub Option 2")
self.subMenu.addAction("Sub Option 3")
self.my_button.installEventFilter(self)
self.buttonMenu.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.ContextMenu:
if source == self.my_button:
self.buttonMenu.exec_(event.globalPos())
return True
elif source == self.buttonMenu:
self.subMenu.exec_(event.globalPos())
return True
return super().eventFilter(source, event)
Upvotes: 3