+1 tag for Google+

Sunday, 30 July 2017

Maya UI Layout Example

In reply to another StackOverflow question, I wrote 2 blocks of code that shows 2 UI layouts created with Maya's UI framework.

First one looks like this:

This is the code that created this first one.

import maya.cmds as mc
def buildUI():
  winName = 'myWindow'
  winWidth = 200 # set a target width and reference this when you specify width
  if mc.window(winName, exists=True):
      mc.deleteUI(winName)
  mc.window(winName, width=winWidth, title='Test Window')
  # i always have keep a reference to the main columnLayout
  mainCL = mc.columnLayout() 
  mc.text(label='text row 1')

  # tmpRowWidth controls the width of my columns in the rowLayout
  # with reference to winWidth
  tmpRowWidth = [winWidth*0.3, winWidth*0.7]
  mc.rowLayout(numberOfColumns=2, columnWidth2=tmpRowWidth)
  # at this point our UI pointer is under the rowLayout
  mc.text(label='row column1', align='center', width=tmpRowWidth[0])
  mc.button(label='column 2', width=tmpRowWidth[1])
  # we've used up number of children components, if you add 1 more, 
  # Maya will throw an error
  # now to move our pointer back up the hierarchy, 
  # which is our main columnLayout, mainCL
  mc.setParent('..') # also can use mc.setParent(mainCL)

  tmpRowWidth = [winWidth*0.5, winWidth*0.5]
  mc.rowLayout(numberOfColumns=2, columnWidth2=tmpRowWidth)
  mc.text(label='row column1', align='center', width=tmpRowWidth[0])
  mc.button(label='column 2', width=tmpRowWidth[1])
  mc.setParent('..')

  tmpRowWidth = [winWidth*0.7, winWidth*0.3]
  mc.rowLayout(numberOfColumns=2, columnWidth2=tmpRowWidth)
  mc.text(label='row column1', align='center', width=tmpRowWidth[0])
  mc.button(label='column 2', width=tmpRowWidth[1])
  mc.setParent('..')

  mc.text(label='text row 3')

  tmpWidth = [winWidth*0.3, winWidth*0.5, winWidth*0.2]
  mc.textFieldButtonGrp(label='txt field', w=winWidth, columnWidth3=tmpWidth, buttonLabel='okay')
  mc.button('full width button', width=winWidth)

  mc.showWindow(winName)
  mc.window(winName, e=True, width=winWidth, height=1)
  return
buildUI()
The second one looks like this:

This features the same controls from the first block of code, being placed into a larger rowLayout, with a small amount of change.

And here's the second block of code that created this:
import maya.cmds as mc
def buildUI():
  winName = 'myWindow'
  winWidth = 400 # set a target width and reference this when you specify width
  if mc.window(winName, exists=True):
      mc.deleteUI(winName)
  mc.window(winName, width=winWidth, title='Test Window')
  # i always have keep a reference to the main columnLayout
  mainCL = mc.columnLayout() 
  mainRLWidth = [winWidth*0.6, winWidth*0.4]
  mainRL = mc.rowLayout(w=winWidth, numberOfColumns=2, columnWidth2=mainRLWidth, rowAttach=(2, 'top', 0))
  mc.columnLayout(w=mainRLWidth[0]) # create a columnLayout under the first row of mainRL
  mc.text(label='mainRL column 1', font='boldLabelFont')
  mc.text(label='')
  mc.text(label='text row 1')

  # tmpRowWidth controls the width of my columns in the rowLayout
  # with reference to winWidth
  tmpRowWidth = [mainRLWidth[0]*0.3, mainRLWidth[0]*0.7]
  mc.rowLayout(numberOfColumns=2, columnWidth2=tmpRowWidth)
  # at this point our UI pointer is under the rowLayout
  mc.text(label='row column1', align='center', width=tmpRowWidth[0])
  mc.button(label='column 2', width=tmpRowWidth[1])
  # we've used up number of children components, if you add 1 more, 
  # Maya will throw an error
  # now to move our pointer back up the hierarchy, 
  # which is our main rowLayout, mainRL
  mc.setParent('..') # also can use mc.setParent(mainRL)

  tmpRowWidth = [mainRLWidth[0]*0.5, mainRLWidth[0]*0.5]
  mc.rowLayout(numberOfColumns=2, columnWidth2=tmpRowWidth)
  mc.text(label='row column1', align='center', width=tmpRowWidth[0])
  mc.button(label='column 2', width=tmpRowWidth[1])
  mc.setParent('..')

  tmpRowWidth = [mainRLWidth[0]*0.7, mainRLWidth[0]*0.3]
  mc.rowLayout(numberOfColumns=2, columnWidth2=tmpRowWidth)
  mc.text(label='row column1', align='center', width=tmpRowWidth[0])
  mc.button(label='column 2', width=tmpRowWidth[1])
  mc.setParent('..')

  mc.text(label='text row 3')
  tmpWidth = [mainRLWidth[0]*0.3, mainRLWidth[0]*0.5, mainRLWidth[0]*0.2]
  mc.textFieldButtonGrp(label='txt field', w=mainRLWidth[0], columnWidth3=tmpWidth, buttonLabel='okay')
  mc.button('full row width button', width=mainRLWidth[0])
  mc.setParent('..') # this will exit the rowLayout back to the mainRL, same as mc.setParent(mainRL)

  mc.columnLayout(width=mainRLWidth[1]) # start another vertical layout
  mc.text(label='mainRL column 2', font='boldLabelFont')
  mc.text(label='')
  mc.text(label='text row 1')
  mc.button(label='button', width=mainRLWidth[1]*0.95, height=70)

  mc.setParent(mainCL) # set UI pointer back under the main columnLayout
  mc.text(label='')
  mc.button(label='full window width button', width=winWidth, height=40)

  mc.showWindow(winName)
  mc.window(winName, e=True, width=winWidth, height=1)
  return
buildUI()

I show that having a good understanding of the hierarchy structure of how we've set up our controls, we can create UI that looks exactly how we want it to.

3 comments:

  1. Hey. This post was super helpful! I saw it on Stack Overflow. Have you ever had any problems adding a 'Refresh' button to a maya window like the ones above? My refresh button calls a function that does a cmds(or mc).ls to fill in a dictionary and then runs the build_UI function. But the window doesn't always rebuild. Do you have any good ideas about this? Thanks!

    ReplyDelete
  2. I might have fixed my problem by not putting any name in showWindow()

    ReplyDelete
    Replies
    1. Hey David! It's great that you managed to find a solution! I have not encountered any problems with showWindow() so far.

      I am guessing it works in your case because showWindow() would show the window last referred to, just like how any added UI controls would automatically be children of the last layout referred to in the code.

      You're a CG artist too? :)

      Delete