1

The following Code is to create a MenuBar in Pyqt5. Want to move the cursor from one menu to another menu by pressing Left/Right Arrow Keys. IF We press the Left Arrow key once, Cursor moves smoothly and focus on pervious Menu. But at the same time, if we press the Right Arrow Keys once, Cursor will not Move to the next menu. Instead of once, We press twice the time, to move the cursor from one menu to the next menu.

For Example: In my script, From, file menu, we press the right arrow keys twice the time, then only the next menu (Accounts menu) Will get focused and so on. But at the same time, if we press the Left arrow key once ( Accounts to file), the previous menu get focused.

My intention: If We press either the Right arrow key or the Left Arrow key once (Instead of twice press), the cursor will move to next or perivous menu. How to resolve it ?

import sys
import os

from PyQt5.QtWidgets import (QMainWindow,QApplication,
                            QWidget,
                            QMdiArea,QMdiSubWindow,
                            QMenuBar,QMenu,QAction,
                             QVBoxLayout,QTabWidget,QTabBar,QTreeView)

from PyQt5.QtCore import pyqtSignal,Qt
from PyQt5.QtGui import QIcon,QPixmap,QColor

def create_icon_by_color(color):
    pixmap = QPixmap(512,512)
    pixmap.fill(color)
    return QIcon(pixmap)

class ME_MainScreen(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Make Easy - Main Screen")
        self.setWindowState(Qt.WindowMaximized)
        self.setMinimumSize(1000,300)

        self.mdi = QMdiArea()
        self.mdi.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdi.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.mdi)
        widget = QWidget()
        widget.setLayout(self.main_layout)
        self.setCentralWidget(widget)

        self.me_mainscreen_menubar_createActions()
        self.me_mainscreen_menubar_createMenus()



    def me_mainscreen_menubar_createActions(self):
        self.exitAct = QAction("E&xit", self, shortcut="Ctrl+Q",statusTip="Exit the application", triggered=self.close)

    def me_mainscreen_menubar_createMenus(self):
        # Create menu bar and add action
        self.me_mainscreen_menuBar = self.menuBar()
        self.me_mainscreen_menuBar.setObjectName("on_self.me_mainscreen_menuBar")

        self.menu_file          = self.me_mainscreen_menuBar.addMenu('&File')
        self.menu_accounts      = self.me_mainscreen_menuBar.addMenu('&Accounts')
        self.menu_inventory     = self.me_mainscreen_menuBar.addMenu('&Inventory')
        self.menu_manufacture   = self.me_mainscreen_menuBar.addMenu('&Manufacture')
        self.menu_payroll       = self.me_mainscreen_menuBar.addMenu('&PayRoll')
        self.menu_others        = self.me_mainscreen_menuBar.addMenu("&Others")
        self.menu_help          = self.me_mainscreen_menuBar.addMenu("&Help")

        self.menu_file_transcation  = self.menu_file.addMenu("&Transcation")
        self.menu_file_reports      = self.menu_file.addMenu("&Reports")
        self.menu_file_master       = self.menu_file.addMenu("Mast&er")
        self.menu_file_settings     = self.menu_file.addMenu("&Settings")
        self.menu_file.addSeparator()
        self.menu_file.addAction(self.exitAct)

        self.menu_accounts_transcation  = self.menu_accounts.addMenu("&Transcation")
        self.menu_accounts_reports      = self.menu_accounts.addMenu("&Reports")
        self.menu_accounts_master       = self.menu_accounts.addMenu("Mast&er")
        self.menu_accounts_settings     = self.menu_accounts.addMenu("&Settings")

        self.menu_inventory_transcation  = self.menu_inventory.addMenu("&Transcation")
        self.menu_inventory_reports      = self.menu_inventory.addMenu("&Reports")
        self.menu_inventory_master       = self.menu_inventory.addMenu("Mast&er")
        self.menu_inventory_settings     = self.menu_inventory.addMenu("&Settings")


def main():
    app = QApplication(sys.argv)
    _mainscreen = ME_MainScreen()
    app.setStyle("Fusion")
    _mainscreen.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
tckraomuqnt
  • 470
  • 4
  • 17
  • 1
    That's because you're adding submenus. The right arrow is supposed to open the items in a sub menu, but you didn't add any item to those actions. If you don't want to receive navigation keys for their menu action, just disable those menus. – musicamante Mar 02 '22 at 00:11

1 Answers1

1

The problem is that when the right arrow is pressed, QMenu checks if the current action is a submenu (action.menu() returns a QMenu or None) and eventually tries to open it. Since all the sub menus you added are empty, nothing happens until the arrow is pressed again.

A possible solution is to use the aboutToShow signal of the parent menu and connect it to a function that checks whether each action is a menu and if it has items, then eventually enable or disable it:

class ME_MainScreen(QMainWindow):
    # ...
    def me_mainscreen_menubar_createMenus(self):
        # ...
        self.menu_file.aboutToShow.connect(self.check_file_menu)

    def check_file_menu(self):
        for action in self.menu_file.actions():
            if action.menu():
                action.setEnabled(bool(action.menu().actions()))

In this way, if the sub menu has no action, it gets disabled (which is also a proper behavior, as if users see an enabled sub menu, they would assume that it contains some items), and keyboard navigation would work properly:

  • if there are no enabled items (all items are disabled), no item gets selected and the right arrow will switch to the next menu;
  • if there are enabled items, the first one will be highlighted;
  • if an highlighted item is a sub menu with actions (so, enabled), the right arrow will open it;
  • if the highlighted item is just a simple action, the right arrow will switch to the next menu;
musicamante
  • 41,230
  • 6
  • 33
  • 58
  • Thanks. Got it. But my intention is, If I press the down arrow key then only submenus (Transaction, Report, Master) will get focused, How to avoid submenus default focus? If we press the Right arrow key cursor will move next menu, without checking the submenus. Is it possible? @musicamante – tckraomuqnt Mar 02 '22 at 01:37
  • @tckraomuqnt are you saying that the sub menus get selected even if they are disabled with the above code? – musicamante Mar 02 '22 at 01:42
  • In My programme, I have submenus with actions. My requirement is, If we press the right arrow key once, the cursor will move to the next main menu(without checking any submenus). But If we press Alt+F, then the first submenu(Transcation) is focused by default. How to avoid it ? @musicamante – tckraomuqnt Mar 02 '22 at 01:49
  • @tckraomuqnt Please answer my question: did you use the above code? Does the first submenu action focused **even if** it is disabled? If so, what OS and Qt version are you using? – musicamante Mar 02 '22 at 01:59
  • sir, as per your code,It's perfect. If no actions then The submenus will be disabled. But in my case, My necessity is absolutely different. I Have a submenu with some actions. In that situation, I Press the Right arrow key, the first submenu action will be focused on. How to avoid it? If I press the Right Arrow keys, I need to focus next main menu only instead of submenus with actions. If I press the down arrow key then only the submenus get focused. @musicamante – tckraomuqnt Mar 02 '22 at 02:05
  • 1
    @tckraomuqnt So you want to override the default behavior, and use the right arrow to select the next menu even if the current action is a submenu? That is probably doable, but I'd strongly suggest to avoid that: it's completely unintuitive and could result very odd: even if keyboard navigation may not be so common nowadays, users that use it are accustomed to that behavior, and not being able to access sub menu items with arrows is annoying. I, for one, would find it **terribly ugly**. Are you really sure about it? Can I ask you why you want to go against such a commonly accepted behavior? – musicamante Mar 02 '22 at 02:15