Python Forum
QMenu tearoff and questions
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
QMenu tearoff and questions
#1
Hi all, I am just starting out in the use of PyQt and already I am having some issues and questions about QMenu. Hoping someone could shed share light on it or share their insights with me.

1. QMenu tearoff
Currently my right click menu consists of 2 or more QMenu. There is the base (1st Tier) and sub-menu (2nd tier) which are added into the base menu option.

While the base menu is tear off, when creating a new menu item, the new item does not reflects in the tear off. It only reflects if I close and do another re-tearoff.

Using my code example below, if you:
  • add in the option - drinks
  • Right mouse click on the drinks tab and click on the tearoff (the first option)
  • Select the option Add Menu Item
  • Note that the new item does not reflects in the current tearoff window, but if you hover back to the drinks tab and right mouse click again, the new option is there.

By the way, this does not seems to be affecting the sub-menus (2nd tier) tearoff.

2. Rename and Remove of QMenu Items
I need some help on this as I am not sure how to proceed with this, or if it is possible to do so as I could not find much information on the QMenu documentation page (maybe there are but not sure which to utilize)

Do I need to create another right click menu for each of the created new menu items (be it the 1st or 2nd tier menus)? Or is there a better way to approach this - eg. mouse double click will allows me to rename etc...


This is my code:


class MyWin(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MyWin, self).__init__()
        central_widget = QtGui.QWidget()
        self.setCentralWidget(central_widget)
        vlay = QtGui.QVBoxLayout(central_widget)
        hlay = QtGui.QHBoxLayout()
        vlay.addLayout(hlay)
        vlay.addStretch()

        self.add_button = QtGui.QToolButton()
        self.tab_bar = QtGui.QTabBar(self)
        self.add_button.setIcon(QtGui.QIcon('add.png'))
        self.add_button.setMenu(self.set_menu())
        self.add_button.setPopupMode(QtGui.QToolButton.InstantPopup)

        self.tab_bar.setTabButton(
            0,
            QtGui.QTabBar.ButtonPosition.RightSide,
            self.add_button
        )
        hlay.addWidget(self.add_button)
        hlay.addWidget(self.tab_bar)

        self.my_extra_menus = defaultdict(list)

    def set_menu(self):
        menu_options = ['food', 'drinks', 'snacks']
        qmenu = QtGui.QMenu(self.add_button)
        for opt in menu_options:
            qmenu.addAction(opt, partial(self.set_new_tab, opt))
        qmenu.addAction
        return qmenu

    def set_new_tab(self, opt):
        self.tab_bar.addTab(opt)

    def mousePressEvent(self, event):
        index = self.tab_bar.tabAt(event.pos())

        if event.button() == QtCore.Qt.RightButton:
            self._showContextMenu(event.pos(), index)

        else:
            super(MyWin, self).mousePressEvent(event)

    def _showContextMenu(self, position, index):
        self.qmenu = QtGui.QMenu(self)
        self.qmenu.setTearOffEnabled(True) # New item is not shown in tearoff mode
        self.qmenu.setTitle(self.tab_bar.tabText(index))

        add_item_action = QtGui.QAction('Add Menu Item', self)
        slot = functools.partial(self._addMenuItem, index)
        add_item_action.triggered.connect(slot)
        self.qmenu.addAction(add_item_action)
        self.qmenu.addSeparator()

        if self.my_extra_menus.get(index):
            for menuItem in self.my_extra_menus[index]:
                self.qmenu.addMenu(menuItem)

        self.qmenu.addSeparator()

        global_position = self.mapToGlobal(self.pos())
        self.qmenu.exec_(QtCore.QPoint(
            global_position.x() - self.pos().x() + position.x(),
            global_position.y() - self.pos().y() + position.y()
        ))

    def _addMenuItem(self, index):
        first_tier_menu = []
        for i in self.qmenu.actions():
            first_tier_menu.append(i.text())

        new_menu_name, ok = QtGui.QInputDialog.getText(
            self,
            "Name of Menu",
            "Name of new Menu Item:"
        )

        if ok:
            if new_menu_name in list(filter(None, first_tier_menu)):
                self.err_popup()
            else:
                menu = QtGui.QMenu(new_menu_name, self)
                menu.setTearOffEnabled(True) # New item is shown in tearoff mode, unless I close and re-tearoff
                add_item_action = QtGui.QAction('Add sub Item', menu)
                slot = functools.partial(self._addActionItem, menu)
                add_item_action.triggered.connect(slot)
                menu.addAction(add_item_action)
                menu.addSeparator()

                self.my_extra_menus[index].append(menu)

    def _addActionItem(self, menu):
        new_item_name, ok = QtGui.QInputDialog.getText(
            self,
            "Name of Menu Item",
            "Name of new Menu Item:"
        )

        second_tier_menu = []
        for i in menu.actions():
            second_tier_menu.append(i.text())

        if ok:
            if new_item_name in list(filter(None, second_tier_menu)):
                self.err_popup()
            else:
                action = QtGui.QAction(new_item_name, self)
                slot = functools.partial(self._callActionItem, new_item_name)
                action.setCheckable(True)
                action.toggled.connect(slot)
                menu.addAction(action)


    def _callActionItem(self, name, flag):
        print name
        print flag


    def err_popup(self):
        msg = QtGui.QMessageBox()
        msg.setIcon(QtGui.QMessageBox.Critical)
        msg.setText("Input name already exists. Please check.")
        msg.setWindowTitle('Unable to add item')
        msg.setStandardButtons(QtGui.QMessageBox.Ok)
        msg.exec_()




win = MyWin()
win.show()
Many thanks in advance for any replies!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Bug [PyQt] Priority problem with PyQt5 QMenu() and QSystemTrayIcon() Alfalfa 1 5,090 May-31-2017, 09:50 PM
Last Post: Alfalfa

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020