MenuItem RMB popup menu or Modifier

189 views
Skip to first unread message

johan Borgström

unread,
Jul 11, 2014, 7:59:42 AM7/11/14
to python_in...@googlegroups.com
Hi!

I am building a basic menu populated with some menuItems. I want the user to be able to add and remove menuItems to the menu. I have wrapped the menu in a class and written some methods to help to add and remove menuItems. I do not want to write a special ui to handle the removing of items, so my idea is to check if the user holds a modifier key while clicking the menuItem and if so delete it. Another idea is to use a right click popup menu on the menuItem and have the option "delete item".
To add the command to the menuItem I use functools.partial. So to wrap it up my questions are:

  • How can I add a right click popup menu to a menuItem.
  • How can I check if a modifier key was pressed when the menuItem was clicked.
Best Regards,
Johan


Marcus Ottosson

unread,
Jul 11, 2014, 8:15:47 AM7/11/14
to python_in...@googlegroups.com

I can’t be sure as I’m not particularly experienced with the menuItem of maya.cmds (which btw I’m assuming that you mean?) but I would assume that by using that particular command you’re most likely bound to the features it exposes.

Having said that, if you were interested in venturing outside of commands-land and into Qt you may have some luck with something like this:

>>> from PySide import QtGui
>>> QtGui.QApplication.queryKeyboardModifiers()

Which will look, in a global fashion, on which keys are being held at the time of invocation.

As for menu within a menu, that sounds like you’ll be best off implementing a menu widget on your own, or perhaps hack the option-box to remove items for you.



--
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/643993ce-63d0-431a-b27e-20568cb74355%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

johan Borgström

unread,
Jul 11, 2014, 9:25:04 AM7/11/14
to python_in...@googlegroups.com
Hi Marcus and thanks!

I have been using PySide for creating other tools, but for some reason I went back to old maya.cmds...
I created a small test snippet, to experiment with the menu.

The small menu test is working as expected, do you know how to add it to the maya main menubar?
Using the snippet below if I add my "Root menu" to the maya mainWindow using the menuBar() to get a reference to the object I get a weird behaviour. Do you know a way to add it ?


#import pprint
#from maya import cmds
from maya import OpenMayaUI as omui
from PySide import QtCore, QtGui
from shiboken import wrapInstance

omui.MQtUtil.mainWindow()    
ptr = omui.MQtUtil.mainWindow()    
#widget = wrapInstance(long(ptr), QtGui.QWidget)
widget = wrapInstance(long(ptr), QtGui.QMainWindow)


test_win = QtGui.QMainWindow(parent=widget)
root_menu = test_win.menuBar().addMenu('Root menu')
sub_menu = root_menu.addMenu("Sub Menu"); 
l_1 = root_menu.addAction("Leaf 1");
l_2 = sub_menu.addAction("Leaf 2"); 
test_win.show()


Best Regards,
Johan

Marcus Ottosson

unread,
Jul 11, 2014, 10:14:43 AM7/11/14
to python_in...@googlegroups.com
I'm surprised you got anywhere with that script to be honest, but one alternative might be to go with QWidget as opposed to QMainWindow as QMainWindow probably tries making a separate window as opposed to an additional widget amongst your menus. In fact, I think QMainWindow should probably never be parented to anything as its more a top-level widget.

But, if your goal is for artists to make their own menus, maybe there is a better way to go about it. The way I've seen it done before is with a separate window, a menu-editor if you will, that would generate the equivalent script in Python or MEL. That way, you'd keep the resulting menus independent of your tool, as well as possibly simplify your debugging.


--
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.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Justin Israel

unread,
Jul 11, 2014, 5:36:14 PM7/11/14
to python_in...@googlegroups.com
I don't think it should be much of a problem to create a QMainWindow that is a child of the Maya main window. It will know it isn't a top-level window. 
But for the menu stuff, it seems like it doesn't work too well to try and create the Application-level menus directly through Qt. You probably need to stick with going through the mel calls, to create the menus and items. 


johan Borgström

unread,
Jul 12, 2014, 6:10:47 AM7/12/14
to python_in...@googlegroups.com
Hi Justin and thanks for your reply,

If I create menu items with cmds.menuItem(...) do you know if I can add a right click popup menu to a menuItem? Or can I check if a modifier was pressed while the user clicks the menu item? I want to create a menu where menu items can be deleted by RMB clicking the item and choosing "delete" from a popup menu. Another way would be to delete the item if a modifier key was pressed during the LMB click. 

The original question was not regarding Qt menus but Since Qt is used in other softwares in would be interesting to do it with Qt, and possible reuse the workflow. 
I had a look into the Maya Main window widget and found a QtGui.QMenuBar which seems to be the menubar that the main menu uses. I added my custom menu to this and it seems to work. This feels really hacky and not that solid to say the least :) but it is fun to experiment.

I am on a mac and I am not sure how the menubar looks on a pc, but it seems like there are two "parallell" menus on mac. If I show the menubar that is found in the Maya main window it appears below the "original main menu". See the image attached. Below is the code that I use to add the menu.

from maya import OpenMayaUI as omui
from PySide import QtCore, QtGui
from shiboken import wrapInstance

# maya main window
ptr = omui.MQtUtil.mainWindow()    
widget = wrapInstance(long(ptr), QtGui.QWidget)
#widget.windowTitle()

# get a reference to the menu bar
menubar = [w for w in widget.children() if isinstance(w, QtGui.QMenuBar) ]
menubar[0].show()

# add menu and menuitems
my_menu = menubar[0].addMenu("My Menu") 
sub_menu = my_menu.addMenu("Sub Menu")
l_1 = my_menu.addAction("Leaf 1")
l_2 = sub_menu.addAction("Leaf 2");

I would be grateful if you have som ideas on how to add RMB popup menus to menu items or checking if a modifier was pressed. But is would also be interesting to se if we can get the Qt approach to work :)

Best Regards,
Johan


On Friday, July 11, 2014 1:59:42 PM UTC+2, johan Borgström wrote:
menubar.jpg

Marcus Ottosson

unread,
Jul 12, 2014, 7:28:29 AM7/12/14
to python_in...@googlegroups.com
Hey Johan,

The snippet I posted above on modifier keys, didn't that work for you?


--
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.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

johan Borgström

unread,
Jul 12, 2014, 8:14:38 AM7/12/14
to python_in...@googlegroups.com
Hi Marcus,

I have not tried that yet. To get a better understanding, I assume that if we use the cmds module to build menus, it creates Qt items "in the background" for us. I guess we need a way to reference theese objects to use Qt functionality?  Would I use "omui.MQtUtil.findControl(widgetStr)" or similar?

It would be great if you could post a working snippet of how to add a menu to the main menu with the desired functionality.

Best Regards,
Johan

On Friday, July 11, 2014 1:59:42 PM UTC+2, johan Borgström wrote:

Justin Israel

unread,
Jul 12, 2014, 6:41:30 PM7/12/14
to python_in...@googlegroups.com
The application-level menus don't respond very well to being manipulated at the Qt layer. If it were your own set of menus in another widget (not application main window menus) you would have a lot more flexibility in doing everything you want. I have menus where I do the same, responding to right clicking of menu items to bring up small context menus, or just having full access to all the events. Maybe it can be done effectively, but I have not been having good results in my attempts.

So for specifically dealing with application menus, you may need to stick with the commands module, and make use of the existing support for having an option box next to your menu item. That option box can either do something right away (which may not be very obvious or descriptive of its intent) or it can bring up a menu to do actions.
from functools import partial 
import maya.cmds as cmds
import maya.mel as mm

# Start the top menu
gMainWindow = mm.eval("$win=$gMainWindow")
cmds.setParent(gMainWindow)
m = cmds.menu("myRootMenu", label="Root Menu") 

# Add items and submenus
m_sub1 = cmds.menuItem(label="Sub Menu", subMenu=True)
m_sub1_item1 = cmds.menuItem(label="Leaf 1")

cmds.setParent(m, menu=True)
m_item1 = cmds.menuItem(label="Leaf 2")
m_item1_opt = cmds.menuItem(optionBox=True)

# Attach a callback to the option box
def handleMenuItem(item, *args):
    print "Do something with", item

cmds.menuItem(m_item1_opt, e=True, stp="python", c=partial(handleMenuItem, m_item1))
And then for finding Qt instances of the menu or the actions, if you want to try and play with them directly:
# finding the menu
ptr = omui.MQtUtil.findControl(m)
qm = wrapInstance(long(ptr), QtGui.QMenu)

# finding the menu item
ptr = omui.MQtUtil.findMenuItem(m_item1)
m_item1_action = wrapInstance(long(ptr), QtGui.QAction)
You will probably find it much easier to do as little as possible with the application level menus and just get them to launch something that you have full control over, like Marcus was suggesting with a custom editor.

-- justin



--
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.

johan Borgström

unread,
Jul 13, 2014, 1:40:03 PM7/13/14
to python_in...@googlegroups.com
Hi Justin!

Thanks for your reply and thanks for your snippet!
The best idea seems to be to stick with creating menus through the cmds module. I will run the command directly on the optionbox click. I agree that it is not that descriptive, but it will be fine for what I am doing. Below is a test snippet I did based on your code.

Again, thanks!

Best Regards,
Johan

from functools import partial 
import maya.cmds as cmds
import maya.mel as mm

if cmds.menu('MayaWindow|my_menu_root', exists=1):
    cmds.deleteUI('MayaWindow|my_menu_root')
 
# Attach a callback to the option box
def optionbox_click(item, *args):
    print('Deleted ', item)
    
    if cmds.menuItem(item, exists=1):
        cmds.deleteUI(item)
    
def item_click(item, *args):
    print('Do something with ', item)
    
       
# ref to maya main menu
gMainWindow = mm.eval('$win=$gMainWindow')

# create my root menu
root_menu = cmds.menu('my_menu_root', label='My menu root', parent=gMainWindow) 

# add menu items
for x in range(5):
    
    # create item
    my_item = cmds.menuItem('item_{0}'.format(x), label='Item {0}'.format(x), parent=root_menu)
    
    # add menu item & optionbox handlers
    cmds.menuItem(my_item, e=True, stp='python', c=partial(item_click, my_item))
    my_item_ob = cmds.menuItem(optionBox=True, c=partial(optionbox_click, my_item))





On Friday, July 11, 2014 1:59:42 PM UTC+2, johan Borgström wrote:
Reply all
Reply to author
Forward
0 new messages