PyMEL embedding layouts

236 Views Asked by At

what's the best way to embed multiple PyMEL layouts in a single form?

For example, for each row of a form, I want to specify that:

  • row one uses a 2-column layout for label+textField pair
  • row two uses a 1-column layout for a menu item that has its own annotation label
  • row three adds a full-width execution button to the 1-column layout
  • all controls scale appropriately if the window is resized by a user

TIA!

import pymel.core as pm

def test(*args):
    print('model name: {}'.format(modelTField.getText()))
    print('model geom: {}'.format(modelMenu.getValue())) 

if pm.window("testUI", ex=1): pm.deleteUI("testUI")
window = pm.window("testUI", t="Test v0.1", w=500, h=200)
mainLayout = pm.verticalLayout() 

# two column layout
col2Layout = pm.horizontalLayout(ratios=[1, 2], spacing=10)
pm.text(label='Model name')

global modelTField
modelTField = pm.textField()

col2Layout.redistribute()

# single column layout
col1Layout = pm.horizontalLayout()

global modelMenu
modelMenuName = "modelMenu"
modelMenuLabel = "Model mesh"
modelMenuAnnotation = "Select which geo corresponds to the model shape"
modelMenu = pm.optionMenu(modelMenuName, l=modelMenuLabel, h=20, ann=modelMenuAnnotation)
pm.menuItem(l="FooShape")
pm.menuItem(l="BarShape") 

# execute
buttonLabel = "[DOIT]"
button = pm.button(l=buttonLabel, c=test)

col2Layout.redistribute()

# display window
pm.showWindow(window)
1

There are 1 best solutions below

1
haggi krey On BEST ANSWER

Since the pm.horizontalLayout() and pm.verticalLayout automatically redistribute the content, you do not need to call the redistribute yourself. But for these functions to work you need a with statement like this:

import pymel.core as pm

def test(*args):
    print('model name: {}'.format(modelTField.getText()))
    print('model geom: {}'.format(modelMenu.getValue())) 

if pm.window("testUI", ex=1): pm.deleteUI("testUI")
window = pm.window("testUI", t="Test v0.1", w=500, h=200)

with pm.verticalLayout() as mainLayout:
    with pm.horizontalLayout(ratios=[1, 2], spacing=10) as col2Layout:
        pm.text(label='Model name'
        global modelTField
        modelTField = pm.textField()

    with pm.horizontalLayout() as col1Layout:        
        global modelMenu
        modelMenuName = "modelMenu"
        modelMenuLabel = "Model mesh"
        modelMenuAnnotation = "Select which geo corresponds to the model shape"
        modelMenu = pm.optionMenu(modelMenuName, l=modelMenuLabel, h=20, ann=modelMenuAnnotation)
        pm.menuItem(l="FooShape")
        pm.menuItem(l="BarShape") 
    
        # execute
        buttonLabel = "[DOIT]"
        button = pm.button(l=buttonLabel, c=test)

# display window
pm.showWindow(window)

To create UI with python it helps a lot if you enclose everything into a class, especially if you use PyMel. This way you could do:

class MyWindow(pm.ui.Window):
    def __init(self):
        self.title = "TestUI"
    def buttonCallback(self, *args):
        do something....

This is very helpful if you have callbacks since everything you need can be accessed from within the class and you need no global variables at all.