Question about refreshing cmds.window - Working on a simple Maya tool in Python

Hey all! I’m working on a Maya script and I’m currently using the basic Maya GUI (Was thinking I’d just revise the tool with PySide later, didn’t want to jump into PySide unless it was really worth it…)

Anyways, I need a way to redraw my cmds.window. I’m adding UI elements to it based on what the user does, and the only way I could find was to cmds.deleteUI my window and then reconstructing it.

Is there a better way to do it?

Thank you!

There is definitely a better way than having to reconstruct your UI each time :).

First, what type of elements / controls are these?

If they are Maya attributes you can use the attr controls that already exist, these update as the attribute is changed on the object. Another way you can do this is by using callbacks to determine if an element has changed and call a refresh at that point.

If you have some code you can post that would be really helpful to see where you are at.

Ya you don’t need to refresh the while ui, you can just set new data on ui components using the edit mode of the command used to make them on a reference string.

Or if your using pymel it will return you a object you can use to interact with existing ui components on creation of them.

Most of my Maya scripts in github show good examples of changing ui content at run time. curvyEdges/scripts/curvyEdges.py at master · cmcpasserby/curvyEdges · GitHub

(not sure if i can legally post this code online :confused: which sucks because I’m sure it’d be more helpful) But I’ll just try to describe it, I’m trying to view cmds.image’s in the cmds.window based on a button click. So users can load in, view and cycle through different images in their GUI window. Nothing to do with attrs. So far I’ve got it to work with deleting/reconstructing UI method, but again I wanted a better way.

Maybe it’s worth just investing time doing this in PyMel? If you think so, what are some good resources I can reference for refreshing windows?

Thanks a ton!

have you tried using image command in edit mode?

cmds.image(myImageReference, e=True, image=myImagePath)

I will try to make a simple test case with both maya.cmds and pymel for you.

Ok i made 2 test cases to show you the syntax for changing a image at run time without reloading the whole UI

maya.cmds


import maya.cmds as cmds


class UI(object):
    def __init__(self):
        title = 'Test Case'
        if cmds.window('testCase01', exists=True):
            cmds.deleteUI('testCase01')

        window = cmds.window('testCase01', title=title, mnb=False, mxb=False, sizeable=False)
        cmds.columnLayout(p=window)
        self.img1 = cmds.image(i=r'C:\Users\Chris\Desktop\1625635_10155390376450173_5469917921630109316_n.jpg')
        cmds.button(label='Change Image', command=self.btnpress)
        cmds.showWindow(window)

    def btnpress(self, *args):
        cmds.image(self.img1, e=True, image=r'C:\Users\Chris\Desktop\Tim.png')


UI()

pyMel


import pymel.core as pm


class UI(object):
    def __init__(self):
        title = 'Test Case 2'

        if pm.window('testCase02', exists=True):
            pm.deleteUI('testCase02')

        with pm.window('testCase02', title=title, mnb=False, mxb=False, sizeable=False) as window:
            with pm.columnLayout():
                self.img1 = pm.image(i=r'C:\Users\Chris\Desktop\1625635_10155390376450173_5469917921630109316_n.jpg')
                pm.button(l='ChangeImage', c=self.btnPress)
        window.show()

    def btnPress(self, *args):
        self.img1.setImage(r'C:\Users\Chris\Desktop\Tim.png')

UI()

generically all changes to existing controls or layouts are just calling <command>(<your_control_here>, e=True, <property>=<value>). That’s pretty easy to handle, and you can easily cover up the wordy syntax with a function or a class. The only part that would be bad would by trying to update a gui from outside the main maya thread, which is a no-no.

More here and some extended discussion of how to go from the imperative syntax to

textbox1.text = 'hello'

here

Awesome, thanks for all your help and example codes everyone! I got it working with passerby’s code with maya.cmds… Now I’m running into problems with maya layouts. Argh, so many limitations.

Anyone on getting a cmds.scrollLayout to resize to fit a dockControl?
Right now I have a window inside a dock control. It has a button and an image. I want the image to be in a scroll layout that resizes with the dock control (if the user resizes the dockControl).

I tried parenting the scrollLayout to dockControl, masterWindow, I tried a frameLayout? But it wasn’t resizing based on those layouts…

Again, let me know if this can be better accomplished another way / another library :slight_smile:

My code goes sorta like this:


import maya.cmds as cmds
import os
import os.path

class MasterWindow(object):
    def __init__(self):
        # delete current instance of window
        if cmds.window('masterWindow', exists=True):
            cmds.deleteUI('masterWindow')
        if cmds.dockControl('masterDockControl', exists=True):
            cmds.deleteUI('masterDockControl')
        
        # formatting
        masterWindow = cmds.window('masterWindow', resizeToFitChildren=False)
        form = cmds.formLayout(parent=masterWindow, numberOfDivisions=100) 
        allowedAreas = ['all']
        masterDockControl = cmds.dockControl('masterDockControl', area='left', content=masterWindow, allowedArea=allowedAreas, sizeable=True)
        
        column = cmds.columnLayout()
        btn = cmds.button(label='Button', width=200)
        cmds.separator(height=10)
                        
        # viewing image
        self.imageScroller = cmds.scrollLayout(width=500, height=500)
        self.currentImage = cmds.image(i="image.png")

MasterWindow()


I usually cheat by arranging it



formLayout
   scrollLayout
      Formlayout
        Contents

attaching the scroll to all sides of the outer form keeps it from shrinking, and it will stretch to accomodate the size of the inner formlayout as that grows for contents

1 Like

Yay, thanks Theodox, it may be cheating but that worked! :):

In the end I had something like this:


import maya.cmds as cmds
import os
import os.path

class WindowClass(object):
    def __init__(self):
        self.title = "MyWindow"
        
        # delete current instance of window
        if cmds.window('masterWindow', exists=True):
            cmds.deleteUI('masterWindow')
        if cmds.dockControl('MyWindow', exists=True):
            cmds.deleteUI('MyWindow')
        
        # formatting
        masterWindow = cmds.window('masterWindow', title='masterWindow', resizeToFitChildren=False)
        form = cmds.formLayout(parent=masterWindow, numberOfDivisions=100) 
        allowedAreas = ['all']
        masterDockControl = cmds.dockControl('MyWindow', area='left', content=masterWindow, allowedArea=allowedAreas, sizeable=True)
        
        mainScrollLayout = cmds.scrollLayout(parent = form)  
        cmds.formLayout(form, edit=True,
        attachForm=(
                    [mainScrollLayout, 'top', 10],
                    [mainScrollLayout, 'left', 0],
                    [mainScrollLayout, 'right', 0],
                    [mainScrollLayout, 'bottom', 2]
                    )
        )
        
        self.scrollingFormLayout = cmds.formLayout(parent = mainScrollLayout, numberOfDivisions=100)

        btn = cmds.button(parent = self.scrollingFormLayout, label='My Content', width=200, height=30)

        cmds.formLayout(self.scrollingFormLayout, edit=True,
                        attachForm=(
                                    [btn, 'top', 10]                                   
                                    )
                        )

        
WindowClass()


It’s not exactly cheating, what you have is a a good way to do it. You’ll probably find as you go along that the number of formlayouts grows and grows, because it’s far easier to do the layouts neatly with them than with other tools. They don’t really cost much and they handle resizing windows and so on much more easily than row and columns. :slight_smile:

Ah okay! Is doing layouts in PySide better?