I am trying to have a QAction in context menu, where I toggle the state of the check box using the following code. But, it is not working. I have also tried checking the box in the beginning (so it does show checked) but it doesn’t get unchecked when I click the updateOn action.
Any suggestions would be greatly appreciated. Thanks in advance
# author = copied from somewhere
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "PyQt5 Context Menu"
self.top = 200
self.left = 500
self.width = 400
self.height = 300
self.InitWindow()
def InitWindow(self):
self.setWindowIcon(QtGui.QIcon("icon.png"))
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.show()
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
updateOn = contextMenu.addAction("Update On")
updateOn.setCheckable(True)
updateOn.setChecked(True)
quitAct = contextMenu.addAction("Quit")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == updateOn:
print("action=", action)
if updateOn.isChecked():
updateOn.setChecked(False)
else:
updateOn.setChecked(True)
if action == quitAct:
self.close()
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
martin
March 29, 2023, 1:43pm
2
Hi @userk182 welcome the forum!
The problem is your updateOn
object is recreated each time the contentMenuEvent
method is called. When you change the checked state at the end, this isn’t stored anywhere and the updateOn
object is deleted and cleared up on exiting the method.
One way to do this would be to store the update on state on the window. This way you can correctly populate the state each time the menu is recreated.
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "PyQt5 Context Menu"
self.top = 200
self.left = 500
self.width = 400
self.height = 300
self.InitWindow()
self._update_on_state = False
def InitWindow(self):
self.setWindowIcon(QtGui.QIcon("icon.png"))
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.show()
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
updateOn = contextMenu.addAction("Update On")
updateOn.setCheckable(True)
print(self._update_on_state)
updateOn.setChecked(self._update_on_state)
quitAct = contextMenu.addAction("Quit")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == updateOn:
self._update_on_state = updateOn.isChecked()
if action == quitAct:
self.close()
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
Alternatively, if you want to persist the state in the menu object (& create it only once) you need to keep a reference to the menu and objects somewhere so they are not cleared up.
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "PyQt5 Context Menu"
self.top = 200
self.left = 500
self.width = 400
self.height = 300
self.InitWindow()
self.context_menu = QMenu(self)
self.context_menu_updateOn = self.context_menu.addAction("Update On")
self.context_menu_updateOn.setCheckable(True)
self.context_menu_updateOn.setChecked(True)
self.context_menu_quitAct = self.context_menu.addAction("Quit")
def InitWindow(self):
self.setWindowIcon(QtGui.QIcon("icon.png"))
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.show()
def contextMenuEvent(self, event):
action = self.context_menu.exec_(self.mapToGlobal(event.pos()))
if action == self.context_menu_updateOn:
pass # is persisted anyway.
if action == self.context_menu_quitAct:
self.close()
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
Hope that helps!