Python + Maya UI?按钮被遮挡了
我不太确定我哪里出错了。我在用Python制作Maya界面方面还是个新手。我的代码有什么问题呢?我希望底部的按钮能占据对话框的整个宽度。我觉得布局是对的,但运行代码时,按钮似乎被某个列挡住了。
'''
John Martini
Quad Sphere 1.0
More info on how to use it can be found at
http://JokerMartini.com
'''
import maya.cmds as cmds
import random
class jmQuadSphere(object):
def __init__(self):
pass
def show(self):
self.GUI()
def GUI(self):
#check to see if our window exists
window = "jmQuadSphere"
if cmds.window(window, exists=True):
cmds.deleteUI(window)
# create our window
window = cmds.window("jmQuadSphere", title = "Quad Sphere", mnb = False, mxb = False, sizeable = False)
cmds.setParent(window)
# Row layout that specifies 3 columns and the width for each column.
cmds.rowColumnLayout('rlOpts', nc=2, cw=[(1,90),(2,90)])
# Each button after the row layout is automatically insterted into the columns numerically
cmds.text( label='Radius:', align='left' )
cmds.floatField('spRadius', minValue=0, maxValue=999999999, value=10, precision=3, step=.01 )
cmds.text( label='Height:', align='left' )
cmds.floatField('spHeight', minValue=0, maxValue=999999999, value=10, precision=3, step=.01 )
cmds.text( label='Width:', align='left' )
cmds.floatField('spWidth', minValue=0, maxValue=999999999, value=10, precision=3, step=.01 )
cmds.text( label='Depth:', align='left' )
cmds.floatField('spDepth', minValue=0, maxValue=999999999, value=10, precision=3, step=.01 )
cmds.text( label='Height Segs:', align='left' )
cmds.intField('spHeightSegs', minValue=0, maxValue=999999999, value=4 )
cmds.text( label='Width Segs:', align='left' )
cmds.intField('spWidthSegs', minValue=0, maxValue=999999999, value=4 )
cmds.text( label='Depth Segs:', align='left' )
cmds.intField('spDepthSegs', minValue=0, maxValue=999999999, value=4 )
cmds.text( label='Roundness:', align='left' )
cmds.floatField('spRoundness', minValue=0, maxValue=100, value=100, precision=2, step=.01 )
cmds.text( label='Flatness:', align='left' )
cmds.floatField('spFlatness', minValue=0, maxValue=100, value=0, precision=2, step=.01 )
cmds.setParent(window)
cmds.rowColumnLayout('rlRun', nc=1)
cmds.button('btnCreateQuadSphere', l="Create", w=180, h=30)
# show window
cmds.showWindow(window)
#execute tool
jmQuadSphere().show()
cmds.scriptEditorInfo(ch=True)
截图:
2 个回答
Maya的用户界面系统背后有一套逻辑。一旦你习惯了这些布局和控件的层级关系,它就会以非常可控和可预测的方式运行。
我用过PyQT(PySide)和Maya的用户界面框架,我觉得Maya的界面一点也不笨重。实际上,Maya的用户界面系统比PyQT更简洁、更省事。用Maya的代码可以用更少的行数实现相同的界面布局和功能。当然,QT最大的优点是它可以跨平台和跨软件使用,这一点就足够让人选择它了。
如果你不打算让你的代码在Maya之外使用,那么使用Maya的用户界面的好处是,命令和你的代码会尽可能长时间地得到支持。
以最近的Maya 2017为例。从Maya 2016开始,用户界面框架切换到了PyQT 5和PySide 2。这会导致之前用PyQt4和PySide 1写的代码无法运行。但是,如果你是用Maya的用户界面系统写的代码,它会继续正常工作。当然,把你的PyQT代码修改为兼容新框架可能只需要在编辑器中搜索和替换,但仍然有可能会出错。
在使用Maya的用户界面时,使用columnLayout
和rowLayout
,你需要注意你创建组件的层级。
rowColumnLayout
可能会让人困惑,因为它同时控制行和列的数量。我通常会使用一个主要的columnLayout
(垂直排列),当我需要多个控件水平排列时,我会单独为那一行使用rowLayout
。
setParent
是你的好帮手。使用setParent
可以把你创建用户界面的“光标/指针”放回到你想要的界面层级下。
在我的第一个示例代码中,我展示了如何用变量存储布局的名称。这样我就可以轻松地在用户界面组件的不同层级之间跳转。
运行我接下来的代码块,看看我们在布局上的灵活性。这对于我在Maya中处理用户界面所需的功能来说已经足够了。
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()
原来的布局仍然在这里,但现在我把它放进了一个更大的rowLayout
的列中。
这是生成这个布局的代码。
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()
希望这能改变你对Maya用户界面系统的看法。它仍然有很多优点。
最重要的是,Maya会尽可能在各个版本中继续支持这些命令,并且在Windows、MacOS和Linux上看起来和表现都很相似。
天哪,我真讨厌Maya的布局。还是用formLayout
吧!(如果不使用QT的话)
看起来rowColumnLayout
的宽度是第一列的宽度,尽管它并不是第一个rowColumnLayout
的子元素。你可以明确设置宽度:
cmds.setParent(window)
cmds.rowColumnLayout('rlRun', nc=1)
cmds.button('btnCreateQuadSphere', l="Create", w=180, h=30)
考虑到你只有一列,没必要用rowColumnLayout
,直接用columnLayout
就行了:
cmds.columnLayout('rlRun', width=180)
截图: