Qaction Shortcut in extended contextmenu not triggered

621 Views Asked by At

I try to extend the contextmenu of a QLineEdit with an additional entry for replacing text. I can extend the contextmenu with .createStandardContextMenu(), which works fine. But when I try to add a shortcut with .setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R)) it will not react on the key. Same with different keys, which I tried. In addition the shortcut made with QAction('&Replace', self) doesn't work too. Some examples here in SO and other sources are constructed in the same way, so I'm wondering that nobody else has got the same problem. Seems that I'm missing anything. But what? I can't figure out, checked the docs multiple times.

Working Example:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys


class ECM(QWidget):

    def __init__(self):
        super(ECM, self).__init__()
        self.setWindowTitle("Extended Context Menu")
        self.lineEdit = QLineEdit()
        self.lineEdit.setContextMenuPolicy(Qt.CustomContextMenu)                            
        self.lineEdit.customContextMenuRequested.connect(self.my_contextMenuEvent)

        layout = QVBoxLayout()
        layout.addWidget(self.lineEdit)
        self.setLayout(layout)

        self.setFixedSize(800,200)
        self.show()

    def replace(self):
        print("replace")

    def my_contextMenuEvent(self):                                           
        print("my_contextMenuEvent")                                         
        menu = self.lineEdit.createStandardContextMenu()
        action = QAction('&Replace', self)
        action.setStatusTip('Replace values')
        action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        action.triggered.connect(self.replace)
        menu.addAction(action)                                               
        menu.exec_()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    sender = ECM()
    app.exec_()
1

There are 1 best solutions below

0
On BEST ANSWER

Based on musicamante's comment I came to the following solution:

Extract from the docs:

  1. If you want to extend the standard context menu, reimplement this function, call createStandardContextMenu() and extend the menu returned.
  2. The default use of the QAction list (as returned by actions()) is to create a context QMenu.

It's not totally logically to me, not for the 1st time ;-)

Final code:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys


class ECM(QWidget):

    def __init__(self):
        super(ECM, self).__init__()
        self.setWindowTitle("Extended Context Menu")
        self.lineEdit = QLineEdit()
        self.lineEdit.setContextMenuPolicy(Qt.CustomContextMenu)                            
        self.lineEdit.customContextMenuRequested.connect(self.my_contextMenuEvent)

        layout = QVBoxLayout()
        layout.addWidget(self.lineEdit)
        self.setLayout(layout)

        self.setFixedSize(800,200)

        action = QAction('&Replace', self)
        action.setStatusTip('Replace values')
        action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        action.triggered.connect(self.replace)

        self.lineEdit.addAction(action)

        self.show()

    def replace(self):
        print("replace")

    def my_contextMenuEvent(self):                                           
        menu = self.lineEdit.createStandardContextMenu()
        menu.addActions(self.lineEdit.actions())
        menu.exec_()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    sender = ECM()
    app.exec_()