Hobby_Devloper
Hobby_Devloper

Reputation: 33

How to activate , ShortCut Key in context menu in pyqt5?

How to activate shortcut key for Context menu item. I try the following things, But the shortcut key was not triggered, but at the same time if we click with the mouse it works fine.

    menu = QMenu()
    atoz_action = QAction(QIcon('d://icon//atoz_4.png'),"Sort A to Z",self)
    atoz_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
    atoz_action.triggered.connect(self.ascending_order)
    menu.addAction(atoz_action)

Addition: Minimal reproducible example As directed by musicamante, I here add a minimal reproducible example.

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

class MyCheckableComboBox(QComboBox):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setEditable(True)
        self.lineEdit().setReadOnly(True)
        self.setStyleSheet("QComboBox QAbstractItemView::item {border: none;padding-left: 5px;}")
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.RightClickMenu)

    def RightClickMenu(self,pos):
       
        menu = QMenu()

        atoz_action = QAction("Sort A to Z",self)
        atoz_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        atoz_action.triggered.connect(self.ascending_order)
        menu.addAction(atoz_action)

        action = menu.exec_(self.mapToGlobal(QPoint(pos)))

    def ascending_order(self):
        print("1111ascending order")


class MyApp(QWidget):

    def __init__(self):
        super().__init__()

        mainLayout = QVBoxLayout()
        self.setLayout(mainLayout)

        self.data = ['America', 'Russia', 'China', 'Germany', 'France', 'India']

        self.combo = MyCheckableComboBox()
        self.combo.setMinimumSize(600,40)

        btn = QPushButton('Print Values')
        btn.clicked.connect(self.getValue)

        mainLayout.addWidget(self.combo)
        mainLayout.addWidget(btn)

        self.combo.addItems(self.data)

    def getValue(self):
        print(self.combo.currentText())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyleSheet('''QWidget {font-size: 20px;}''')
    myApp = MyApp()
    myApp.show()
    app.exit(app.exec_())

Upvotes: 0

Views: 639

Answers (1)

musicamante
musicamante

Reputation: 48231

A keyboard shortcut is only active as long as it's created within its context.

There are many issues about this aspect within your code, but, most importantly:

  • RightClickMenu is a function that is called only whenever the customContextMenuRequested signal is emitted: before that, the action doesn't exist, so there is absolutely no way that it could get triggered;
  • the menu created within that function only exists within the scope of that function; since the menu has no parent, it will be destroyed as soon as the function will return (and its action along with it);
  • creating an action with a parent is not enough to make it "active", you must also call addAction(): QAction ownership doesn't automatically activate the action, especially if the action is triggered by a shortcut that has a more broad context (which is the default);

Other relatively minor (but still important) issues:

  • the CustomContextMenu policy is useful for external objects (normally, parents); if you need to handle a context menu event, you should override contextMenuEvent() (as already explained in my answer to your previous question);
  • only classes and constants should have capitalized names, not functions;
  • the creation of QObjects with parents should be done with major awareness, otherwise they will just be kept alive even when they are not needed anymore; actions of a temporary menu should use the menu as parent, or added using QMenu.addAction();
class MyCheckableComboBox(QComboBox):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setEditable(True)
        self.lineEdit().setReadOnly(True)
        self.setStyleSheet("QComboBox QAbstractItemView::item {border: none;padding-left: 5px;}")

        self.atozAction = QAction("Sort A to Z", self)
        self.atozAction.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
        self.addAction(self.atozAction)
        self.atozAction.triggered.connect(self.ascending_order)

    def contextMenuEvent(self, event):
        menu = QMenu()
        menu.addAction(self.atozAction)
        menu.exec_(event.globalPos())

    def ascending_order(self):
        print("1111ascending order")

Upvotes: 2

Related Questions