Getting started

Steve Theodore edited this page Aug 25, 2017 · 10 revisions

Installation

Installation is simple: just make sure that the mGui folder (the root one containing __init__.py, 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.

Importing

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

or

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 Button('b', w=100).

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_controls and 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))

Nested layouts

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 Text, a ScrollLayout and a RowLayout. The 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.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.