Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Installation is simple: just make sure that the mGui folder (the root one containing
bindings.py and so on) is in your python path.
If you want to avoid loose files you can zip the root mGui folder and add that zip to your path instead; that will work the same way. If you downloaded a zipped copy of the repo from CreativeCrash, just put that zip into a folder on your Maya python path.
The most common use case is to import everything in mGui.gui. Depending on your personal style you can write
from mGui.gui import * with Window('root') as w: with ColumnLayout('col'): Text('txt', label = 'Example') w.show()
import mGui.gui as gui with gui.Window('root') as w: with gui.ColumnLayout('form'): gui.Text('txt', label = 'Example') w.show()
These are interchangeable.
mGui.gui is designed to be safe for star imports.
Learning the toolkit
All of the base mGui classes correspond to commands and widgets in maya.cmds. The only difference in naming is that the mGui versions (being classes) as capitalized. Thus:
cmds.button = Button cmds.menu = Menu cmds.columnLayout = ColumnLayout
and so on. All of the flags from the maya.cmds version are supported as well. The version here on github uses only the long names of the flags (ie,
Button('b', width=100) rather than
If you'd rather use short flag names, you can regenerate your local copy of mGui.core.controls and mGui.core.layouts using the functions
generate_layouts functions in mGui.helpers. More discussion here
New things to learn
There are two key differences in usage.
mGui objects are classes, not commands
This is mostly a semantic issue, but
mGui.gui.Button is a class while
cmds.button is a function. Since the gui widgets get created when the class is instantiated the written code will be almost the same. The real benefits of the class come when you need to do more complex setup, since you can get and set class properties far easily than you can query or edit command objects:
b = Button('go') b.label = 'some very long string' b.width = len(b.label) * 10 b.backgroundColor = (1,1,0)
as opposed to
b = cmds.button('go') cmds.button(b, e=True, label = 'some very long string') cmds.button(b, e=True, width = len(cmds.button, b, q=True, label=True) * 10) cmds.button(b, e=True, backgroundColor = (1,1,0))
mGui layout objects are python context managers, which means they support the
with statement. This allows you to see the scope of your layouts clearly:
with Window('w', title = 'example') as w: with ColumnLayout('main'): Text(None, label = 'Header text', align = 'center') with ScrollLayout('scroll'): with ColumnLayout('subscroll') Button(label = 'inside a scroll layout') Button(label = 'inside a scroll layout') Button(label = 'inside a scroll layout') with RowLayout('bottom', numberOfChildren=2): Button(label = 'cancel') Button(label = 'activate')
In this example the window has 3 immediate children - a
ScrollLayout and a
ScrollLayout and the
RowLayout have their own children. The context manager makes it obvious who belongs to whom.
Keys and addresses
Managing a gui is usually kind of tedious. In vanilla Maya gui code, you frequently need to store a lot of gui widgets in variables, since that's the only way to query or edit their properties.
mGui allows you to access gui widgets using a property-like syntax. Since most gui is arranged in some kind of tree (a window contains a layout, the layout contains widgets or other layouts, and so on) this allows you to get at your gui elements without a complex system of variables to track things.
mGui assigns these labels based on local variables you declare as you lay out your gui. These local variables are "captured" by the various layout context managers and become the names of the objects. It's easier to see than to explain:
with Window(title = 'main window') as my_window: # create a window, 'my_window' with HeaderForm() as main: # a HeaderForm has two children with VerticalForm() as header: Text("This is an example") more_button = Button("Click for more details") with FooterForm() as body: # a FooterForm also expects two children content_list= TextScrollList() # a list to hold some data delete_btn = Button("delete") # a button to manipulate stuff # add a handler to the 'click for details' button, using the dotted property access my_window.main.header.more_button.command += some_function # add some items to the list my_window.main.body.content_list.items = ['some stuff', 'some more stuff'] # change the label of the delete button my_window.main.body.delete_btn.label = "Remove"
As you can see here the local variables are captured by the layouts and turned into property names. These property names are not the same as the underlying Maya widget names -- but that's OK. You only interact with the widgets through the mGui objects, which are grouped for you automatically. This is a much easier set of data to manage than many independent individual variables. For items you don't care about (such as that
Text() item, which you won't be changing again`) you don't need to store a variable if you don't want it.
It is worth pointing out that you want to avoid name clashes between your gui widgets and the pre-existing properties on the layouts! Don't name use local variables to name a control 'backgroundColor', for example, or you will get the backgroundColor property of the owning layout instead of the child control.