New items are not added into QMenu

39 views
Skip to first unread message

likage

unread,
Jan 14, 2019, 7:05:56 PM1/14/19
to Python Programming for Autodesk Maya
Hi everyone, I have a tool which utilizes QTabWidget and the tabs are populated with a list of keys from within a dictionary.
Each of the QMenu are equipped with 3 default options, with one of the option called `Add new item` where when User uses that option, a prompt dialog will popped up and adds in the user-inputted naming as a new menu option into the current QMenu of the tab (where the right mouse click happens on)

The problems that I am encountering right now is:
1. 2 of the default items in the QMenu are getting added more than once, depending on the number of right mouse clicks made on the tool within the session
2. no new item are added into the QMenu - after I added in a new name for the prompt > when performing another right-click, the menu is still showing the default items plus 2 additional default items as mentioned in #1

Even so, wondering if this is a possible scenario for tabs + qmenu(s)?
I asked this because when doing a google search online, it seems that QMenu is generally used as a generic menu (eg. multiple buttons adopts the same menu etc)

Or should I be adopting to use a different widget for my case?

Tenghao Wang

unread,
Jan 14, 2019, 10:23:26 PM1/14/19
to python_in...@googlegroups.com
Hey likage:

I cannot repro your second question. Items are added properly into the QMenu on my site. For your second question, because you put the "addAction" (2 of the default items)  under the "_showContextMenu" , so theyare added  when you right clicking the tab.
To be noticed, I am using Pyside2, so I placed all the QtGui to QtWidgets.

I paste the new code, hope that helps:
from PySide2 import QtWidgets
from PySide2 import QtCore

class TabBar(QtWidgets.QTabBar ):
    def __init__(self, parent=None):
        super(TabBar, self).__init__(parent)

        self.qmenu = QtWidgets.QMenu()
        self.setExpanding(False)

        add_item_action = QtWidgets.QAction('Add new item', self,
            triggered=self.add_new_item)
        self.qmenu.addAction(add_item_action)
        self.qmenu.addSeparator()
        def_item_01 = self.qmenu.addAction("Default Item A")
        def_item_02 = self.qmenu.addAction("Default Item B")
        self.separator =  self.qmenu.addSeparator()

    def tabSizeHint(self, index):
        return super(TabBar, self).tabSizeHint(index)

    def mousePressEvent(self, event):
        index = self.tabAt(event.pos())
        if event.button() == QtCore.Qt.RightButton:
            self._showContextMenu(event.pos(), index)
        else:
            super(TabBar, self).mousePressEvent(event)

    def _showContextMenu(self, position, index):
        # Default items

        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()
        ))


    @QtCore.Slot()
    def add_new_item(self):
        new_item_name, ok = QtWidgets.QInputDialog.getText(
            self,
            "name of item",
            "Name of new item : "
        )
        if ok:
            new_action = QtWidgets.QAction(new_item_name, self.qmenu, checkable=True)
            self.qmenu.insertAction(self.separator, new_action)


class TabWidget(QtWidgets.QTabWidget):
    def __init__(self, parent=None):
        super(TabWidget, self).__init__(parent)
        self.setTabBar(TabBar(self))

    def resizeEvent(self, event):
        self.tabBar().setMinimumWidth(self.width())
        super(TabWidget, self).resizeEvent(event)


class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.tabs = TabWidget(self)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.tabs)

        some_tabs = ['TabA', 'TabB', 'TabC', 'TabD']
        for my_tab in some_tabs:
            self.tabs.addTab(QtWidgets.QWidget(self), my_tab)
            
test = Window()
test.show()

Tenghao Wang
Sr. Technical Artist
Visual Concepts

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/b9cccfda-a8c5-4f00-bcd2-689ea4777640%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

likage

unread,
Jan 15, 2019, 3:38:50 PM1/15/19
to Python Programming for Autodesk Maya
Hi, thanks for getting back to me. It seems that the newly added items are added to the end (bottom) of the QMenu instead of in-between the 'Add new item' and the 'Default Item'..

Also as mentioned in my first post, is it possible to create different QMenus for different tabs?
Eg. I create 'item01' for TabA and I created 2 new items - 'item01a' and 'item01b' for TabB...  And based on which tabs that I perform a right-mouse click on, it will show the update menu

Justin Israel

unread,
Jan 15, 2019, 5:22:09 PM1/15/19
to python_in...@googlegroups.com
On Wed, Jan 16, 2019 at 9:38 AM likage <dissid...@gmail.com> wrote:
Hi, thanks for getting back to me. It seems that the newly added items are added to the end (bottom) of the QMenu instead of in-between the 'Add new item' and the 'Default Item'..

The documentation for insertAction(before, action) says it will insert the new action *before* the given one, so I would have expected it to put them before the separator. But it also says it will end up appending it if "before" is not a valid action for the menu.
  

Also as mentioned in my first post, is it possible to create different QMenus for different tabs?
Eg. I create 'item01' for TabA and I created 2 new items - 'item01a' and 'item01b' for TabB...  And based on which tabs that I perform a right-mouse click on, it will show the update menu

This should be possible with the available functionality of a QTabBar. I imagine the following aspects would come into play:
  • A dictionary of tab to QMenu and creating a new one if needed
  • Maybe implementing tabInserted and tabRemoved methods if you want to directly track the tabs and create/remove menus at this stage
  • Checking tabAt(point) in your content menu handler to look up the correct QMenu to exec
 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

likage

unread,
Jan 15, 2019, 8:17:29 PM1/15/19
to Python Programming for Autodesk Maya
Thanks for the information, Justin.
After re-arranging the `self.separator` I managed to get the newly created items to be slotted into the specified position of mine.

While this seems to be working, as I tried to implement in the same makings into my actual tool, I keep getting `RuntimeError: Internal C++ object (PySide2.QtWidgets.QAction) already deleted.`, seemingly the `self.separator` got killed off in the midst of it.
The code structure in my actual tool is almost the same as the one that I have posted in this thread, with the exception that I have 'watered' down the code in this thread in hopes of keeping it short and simple.

Even so, wondering if you may any advice to this? Read online for this issue is to make it into a variable in which I did, but still it did not work. 
However, if I do the following:
def mousePressEvent(self):
   
self.separator =  self.qmenu.addSeparator()
   
...

items can still be created and added into the menu, but this time round, each will be created with both the item and the separator altogether

Justin Israel

unread,
Jan 16, 2019, 1:12:04 AM1/16/19
to python_in...@googlegroups.com
I'm not sure which part of your code that C++ error corresponds with, but it means that it was parented to a QObject that was deleted but you are still accessing the python object. If you are able to reproduce it in your public code and know which part it corresponds with, that would be easier to investigate. 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages