单击时打印按钮的标签

时间:2016-05-04 18:00:28

标签: python maya

因此我按下时会尝试输出按钮的标签(按钮标签应该替换buttonNumber功能打印中的XXX)。我不知道如何从按钮中检索标签数据以输出。有什么想法吗?提前致谢

import maya.cmds as mc

def buttonNumber(*args):
    print 'Button XXX was pressed'

def openWindow():
    if mc.window('windowTest', ex=True):
        mc.deleteUI('windowTest', window=True)

    mc.window('windowTest', title='', s=True, resizeToFitChildren = True,)
    mc.rowColumnLayout(numberOfColumns = 3, columnWidth = [ (1, 150), (2, 150), (3, 150)])
    mc.button(label='1', command=buttonNumber)
    mc.button(label='2', command=buttonNumber)
    mc.button(label='3', command=buttonNumber)
    mc.button(label='4', command=buttonNumber)
    mc.button(label='5', command=buttonNumber)
    mc.button(label='6', command=buttonNumber)
    mc.button(label='7', command=buttonNumber)
    mc.button(label='8', command=buttonNumber)
    mc.button(label='9', command=buttonNumber)
    mc.showWindow('windowTest')

openWindow()

4 个答案:

答案 0 :(得分:2)

我建议你在stackoverflow上阅读关于Partial的其他帖子(注意还有另一种方法用Lambda)

我没有测试下面的代码(我这里没有maya,但你会得到这个想法)

import maya.cmds as mc
from functools import partial

def buttonNumber(label, *args):
    print('Button {0:03d} was pressed'.format(label))

def openWindow():
    if mc.window('windowTest', ex=True):
        mc.deleteUI('windowTest', window=True)

    mc.window('windowTest', title='', s=True, resizeToFitChildren = True,)
    mc.rowColumnLayout(numberOfColumns = 3, columnWidth = [ (1, 150), (2, 150), (3, 150)])
    mc.button(label='1', command=partial(buttonNumber, 1))

    mc.showWindow('windowTest')

openWindow()

答案 1 :(得分:2)

正如@DeWeeny所说,您可以使用functools.partial对象将值绑定到按钮命令。您也可以使用函数工厂为这个非常简单的应用程序执行此操作,或者使用可记住的类来记住每个实例的值。

功能工厂

def make_callback(value):
    def inner_callback(_):
        print value, "was clicked"
return inner_callback


w = cmds.window()
c = cmds.columnLayout()
for n in range(9):
    cmds.button( label = str(n), command = make_callback(n))

cmds.showWindow(w)

唯一的微妙之处是inner_callback有一个未使用的参数(_),它需要它,因为按钮回调总是触发一个无用的参数

如果数据比函数工厂示例

更复杂或需要更多计算,这将非常有用
class NumberCallback(object):
    def __init__(self, id):
        self.id = 
def __call__(self, _):
    print self.id, "was clicked"

w = cmds.window()
c = cmds.columnLayout()
for n in range(9):
    cmds.button( label = str(n), command = NumberCallback(n))

cmds.showWindow(w)

这在功能上是相同的但是如果你必须做一些更复杂的行为,一个类会使它整洁

不是lambda

您可以在网上找到使用lambda进行操作的建议。对于很多很棒的应用程序 - 但不要在循环中执行。如果你这样做:

def clicked(num):
    print num, "was clicked"

w = cmds.window()
c = cmds.columnLayout()
for n in range(9):
    cmds.button( label = str(n), command = lambda p: clicked(n))

cmds.showWindow(w)

所有按钮都会响应

8 was clicked

因为lambda会全部捕获循环中的最后一个变量,而这并不是你想要的。

更多详情here。还有一个特定于maya的模块,用于完成此类事件here

答案 2 :(得分:1)

我前段时间在博客上做了一点提醒,能够测试所有不同的本机Maya UI使用命令的方式,并快速测试它们:

  • 经典玛雅字符串
  • 作为参数
  • 拉姆达
  • functools.partial
  • pymel.core.Callback

每个案例都给出了将变量作为参数传递给这些函数的示例。因为有时你必须能够。 总的来说,我完全推荐使用 functools.partial ,它只提供优于其他的优势(如果你忘了PySide)。

Maya UI types

def function(*args):
    print args
    cmds.textFieldGrp(text, edit=True, text=str(args))

variable = 'Variable'
width = [1, 250]
align = [1, 'left']
window = cmds.window(title='UI and commands arguments.')
cmds.columnLayout()

cmds.textFieldGrp(label="\"function()\"", changeCommand="function()", columnWidth=width, columnAlign=align)
cmds.textFieldGrp(label="function", changeCommand=function, columnWidth=width, columnAlign=align)
cmds.textFieldGrp(label="\"function(variable)\"", changeCommand="function(variable)", columnWidth=width, columnAlign=align)
cmds.textFieldGrp(label="lambda x: function(variable)", changeCommand=lambda x: function(variable), columnWidth=width, columnAlign=align)
cmds.separator(style="double", height=20)

import functools
cmds.textFieldGrp(changeCommand=functools.partial(function), label='functools.partial(function)', columnWidth=width, columnAlign=align)
cmds.textFieldGrp(changeCommand=functools.partial(function, variable), label='functools.partial(function, variable)', columnWidth=width, columnAlign=align)
cmds.separator(style="single", height=20)

import pymel.core
cmds.textFieldGrp(changeCommand=pymel.core.Callback(function), label='pymel.core.Callback(function)', columnWidth=width, columnAlign=align)
cmds.textFieldGrp(changeCommand=pymel.core.CallbackWithArgs(function), label='pymel.core.CallbackWithArgs(function)', columnWidth=width, columnAlign=align)
cmds.textFieldGrp(changeCommand=pymel.core.CallbackWithArgs(function, variable), label='pymel.core.CallbackWithArgs(function, variable)', columnWidth=width, columnAlign=align)

cmds.separator(style="single", height=20)
text = cmds.textFieldGrp(label='RESULT: ', text='', width=500)
cmds.showWindow()

使用班级时

因为它不是在考虑课堂的情况下制作的,所以当你在课堂上时,某些方法根本不起作用。

class MayaUI():
    def __init__(self):
        self.variable = 'Variable'
        self.width = [1, 250]
        self.align = [1, 'left']
        self.window = cmds.window(title='UI and commands arguments.')
        cmds.columnLayout()

        cmds.textFieldGrp(label="\"self.function()\"", changeCommand="self.function()", columnWidth=self.width, columnAlign=self.align)
        cmds.textFieldGrp(label="self.function", changeCommand=self.function, columnWidth=self.width, columnAlign=self.align)
        cmds.textFieldGrp(label="\"self.function(self.variable)\"", changeCommand="self.function(self.variable)", columnWidth=self.width, columnAlign=self.align)
        cmds.textFieldGrp(label="lambda x: self.function(self.variable)", changeCommand=lambda x: self.function(self.variable), columnWidth=self.width, columnAlign=self.align)
        cmds.separator(style="double", height=20)

        import functools
        cmds.textFieldGrp(changeCommand=functools.partial(self.function), label='functools.partial(self.function)', columnWidth=self.width, columnAlign=self.align)
        cmds.textFieldGrp(changeCommand=functools.partial(self.function, self.variable), label='functools.partial(self.function, self.variable)', columnWidth=self.width, columnAlign=self.align)
        cmds.separator(style="single", height=20)

        import pymel.core
        cmds.textFieldGrp(changeCommand=pymel.core.Callback(self.function), label='pymel.core.Callback(self.function)', columnWidth=self.width, columnAlign=self.align)
        cmds.textFieldGrp(changeCommand=pymel.core.CallbackWithArgs(self.function), label='pymel.core.CallbackWithArgs(self.function)', columnWidth=self.width, columnAlign=self.align)
        cmds.textFieldGrp(changeCommand=pymel.core.CallbackWithArgs(self.function, self.variable), label='pymel.core.CallbackWithArgs(self.function, self.variable)', columnWidth=self.width, columnAlign=self.align)

        # A bit more complicated
        _map = {'textFieldGrp': lambda arg:cmds.textFieldGrp(arg, query=True, text=True)}
        _com = lambda *args:args[0](self.variable, _map[args[1]](args[2]))
        cmds.textFieldGrp('textfieldName', changeCommand=pymel.core.Callback(_com, self.function, 'textFieldGrp', 'textfieldName'), label="pymel.core.Callback(_com, self.function, 'textFieldGrp', 'textfieldName') + lambdas", columnWidth=self.width, columnAlign=self.align)

        cmds.separator(style="single", height=20)
        self.text = cmds.textFieldGrp(label='RESULT: ', text='', width=500)
        cmds.showWindow()

    def function(self, *args):
        print args
        cmds.textFieldGrp(self.text, edit=True, text=str(args))

MayaUI()

答案 3 :(得分:0)

这是我的代码,可以满足您的需求。

我没有硬编码每个按钮标签的参数以在按钮创建时传递给函数,而是将按钮的对象名称传递给函数。这样,可以随时查询按钮的所有属性(包括标签)。

为了表明这一点,我做了一个随机函数,生成随机字母数字字符串并将它们分配给按钮标签。

它会让你娱乐30秒。试试吧!

screenshot 1

import maya.cmds as mc
import random, string
from functools import partial

def randomButtonTest():
    buttonsList = []
    numButtons = 5
    winName = 'randomButtonWin'
    winWidth = 250
    statusTfgName = 'myStatusTfg'
    buttonLabelLength = 10

    def generateRandomLabel(myLength):
        # generates a random string of characters of myLength
        randomCandidatesList = list(string.ascii_letters + string.digits)
        random.shuffle(randomCandidatesList)
        randomCandidatesStr = ''.join(randomCandidatesList)
        return ''.join([randomCandidatesStr[random.randint(0,len(randomCandidatesStr)-1)] for x in range(myLength)])

    def reportButtonLabel(whichButton, *args):
        buttonLabel = mc.button(whichButton, q=True, label=True)
        print 'reportButtonLabel: clicked - %s' % buttonLabel
        mc.textFieldGrp(statusTfgName, e=True, text=buttonLabel)
        return

    def randomiseButtonClicked(*args):
        mc.textFieldGrp(statusTfgName, e=True, text='')
        for thisButton in buttonsList:
            currentLabel = mc.button(thisButton, q=True, label=True)
            newLabel = '%s: %s' %(currentLabel.split(':')[0], generateRandomLabel(buttonLabelLength))
            mc.button(thisButton, e=True, label=newLabel)
        return

    # build UI
    if mc.window(winName, exists=True):
        mc.deleteUI(winName)
    mc.window(winName, title='Randon Button Labels', w=winWidth )
    mc.columnLayout(w=winWidth)

    # create numButtons number of buttons
    for buttonId in range(numButtons):
        buttonsList.append(mc.button(label='button %i:'%buttonId, w=winWidth ))
        mc.button(buttonsList[-1], e=True, command=partial(reportButtonLabel, buttonsList[-1]))
    mc.text(label='')
    mc.textFieldGrp(statusTfgName, label='Button clicked', w=winWidth, columnWidth2=[winWidth*0.3, winWidth*0.65])
    mc.text(label='')
    mc.button('Randomise labels', w=winWidth, command=randomiseButtonClicked)

    randomiseButtonClicked()
    mc.window(winName, e=True, w=winWidth, h=150, resizeToFitChildren=True)
    mc.showWindow(winName)

randomButtonTest()