Search code examples
pythonmaya

Maya Python: Accessing outer function variable from inner function


I want to write a UI window using python, the following is my code, the function is running correctly, but there is a problem, when I choose an item in the textScrollList, it should call the inner function 'update()' and highlight the corresponding object in the scene. However, the object cannot be chosen correctly and it shows an error message like this:

"Object 'alertWindow|formLayout164|textScrollList27' not found."

I think this happens because the inner function update() cannot access the variable tsl in the outer function, does anyone know how I can revise my code?

def alertWindow():
    if(cmds.window('mainWindow', q =True, exists = True,)):
        cmds.deleteUI('mainWindow')
    UI = cmds.window('mainWindow', title = 'Alert!', maximizeButton = False,   minimizeButton = False, resizeToFitChildren = True, widthHeight = (250, 300), sizeable = False)
    myForm=cmds.formLayout(  )

    txt = cmds.text(label = 'Please check the following objects :')
    tsl = cmds.textScrollList(width = 200, height = 200, enable = True, allowMultiSelection = True, selectCommand = 'update()') 

    count = len(obj)
    for i in range(count):
        cmds.textScrollList(tsl, edit=True, append = obj[i])

    delete = cmds.button(label = 'delete', width = 100, command = 'remove()')
    clz = cmds.button(label = 'Close', width = 100, command = 'cmds.deleteUI("mainWindow")')

    cmds.formLayout(myForm, edit = True, attachForm = [(txt, 'top', 20),(txt, 'left', 65),(tsl, 'left', 25),(tsl, 'top', 50),(delete,'bottom',10),(delete,'left',15),(clz,'bottom',10),(clz,'right',20)])
    cmds.showWindow(UI)

    def update():
        cmds.select(cmds.textScrollList(tsl, q=True, selectItem = True))

    def remove():
        cmds.DeleteHistory()
        cmds.textScrollList(tsl, edit=True, removeItem = cmds.ls(sl=True))

Solution

  • You need to define your inner functions first, then just reference them, no need to use a string for command= :

    def alertWindow(obj):
        def update():
            cmds.select(cmds.textScrollList(tsl, q=True, selectItem = True))
    
        def remove():
            cmds.DeleteHistory()
            cmds.textScrollList(tsl, edit=True, removeItem = cmds.ls(sl=True))
    
        if(cmds.window('mainWindow', q =True, exists = True,)):
            cmds.deleteUI('mainWindow')
        UI = cmds.window('mainWindow', title = 'Alert!', maximizeButton = False,   minimizeButton = False, resizeToFitChildren = True, widthHeight = (250, 300), sizeable = False)
        myForm=cmds.formLayout(  )
    
        txt = cmds.text(label = 'Please check the following objects :')
        tsl = cmds.textScrollList(width = 200, height = 200, enable = True, allowMultiSelection = True, selectCommand = update) 
    
        count = len(obj)
        for i in range(count):
            cmds.textScrollList(tsl, edit=True, append = obj[i])
    
        delete = cmds.button(label = 'delete', width = 100, command = remove)
        clz = cmds.button(label = 'Close', width = 100, command = 'cmds.deleteUI("mainWindow")')
    
        cmds.formLayout(myForm, edit = True, attachForm = [(txt, 'top', 20),(txt, 'left', 65),(tsl, 'left', 25),(tsl, 'top', 50),(delete,'bottom',10),(delete,'left',15),(clz,'bottom',10),(clz,'right',20)])
        cmds.showWindow(UI)
    
    
    
    
    cmds.polyCube()
    alertWindow(['pCube1'])
    

    You could also use a class to keep the state of things.