Maya / Python:在循环生成的UI中创建唯一命令

时间:2017-07-30 02:04:55

标签: python loops user-interface maya autodesk

在Autodesk Maya中,我根据用户想要制作的楼层数动态创建UI(变量numFloors是从intField获取的)。对于每个楼层,我想制作一个按钮,改变相机的高度,以查看地板(这是建筑物)。我遇到的问题是我不能让我的viewFloor()函数知道按下了哪个按钮才能激活它。每次按钮都会通过最近的楼层而不是特定的楼层。

我知道为什么会发生这种情况,在创建按钮时不会动态存储命令,因此当单击按钮时,该命令使用变量的最新实例,该实例应该是等于变量numFloors。

for i in range(0, numFloors):
    floor = i
    btnName = 'floor'+str(floor)+'ViewBtn'
    btnLabel = "view Floor " + str(floor)
    btnCmdVar = str(floor)
    cmds.button(btnName, label= btnLabel, w=20, h=20, command=lambda 
    arg:self.viewFloor(btnCmdVar))

def viewFloor(self, arg):
    print "arg = " + str(arg)

因此,当numFloors = 4时,无论按下哪个楼层按钮,viewFloor都会传递4个。就像我说的那样,我知道为什么会发生这种情况,这段代码片段只是我创建一段代码片段的最好机会,这段代码可以传达我想要做的事情。不幸的是,我不知道如何实现这一目标。

我的一些想法是:

一些复杂的setattr和getattr设置(但我不知道它是如何工作的)

或者一个scriptJob,它检测按钮何时被按下并将该特定按钮的名称传递给viewFloor函数(然后我可以从字符串中拉出数字以获得发言权)。但是,我无法找到在Maya Python文档中按下按钮时发生的事件或条件的任何指示。因此,我无法创建scriptJob。

如果有人能指出我正确的方向(例如我可能需要的scriptJob标志或者setattr getattr设置的例子)或任何其他解决方案,我甚至没有受过教育甚至设想它将非常感激。提前感谢您的任何帮助!

2 个答案:

答案 0 :(得分:2)

这是lambda工作方式的一个众所周知的问题:它记录在案here

您可以通过以下两种方式解决这个问题:

使用func (r *ItemRepository) UpdateByID(itemId int, item *domain.Item) error { var err error if item.Tax == nil { _, err = r.db.Exec(` UPDATE item SET tax_id = ?, name = ?, description = ?, price = ? WHERE id = ? LIMIT 1 `, "NULL", item.Name, item.Description, item.Price, itemId) } else { _, err = r.db.Exec(` UPDATE item SET tax_id = ?, name = ?, description = ?, price = ? WHERE id = ? LIMIT 1 `, item.Tax.ID, item.Name, item.Description, item.Price, itemId) } if err != nil { return err } return nil } 而不是lambda

functools.partialfunctools模块中的一个对象,它将可调用和参数绑定在一起。您几乎可以像使用lambda一样使用它:

functools.partial

按照功能

from functools import partial


for i in range(0, numFloors):
   floor = i
   btnName = 'floor'+str(floor)+'ViewBtn'
   btnLabel = "view Floor " + str(floor)
   cmd = partial(self.viewFloor, i)
   cmds.button(btnName, label= btnLabel, w=20, h=20, command=cmd)

这里嵌套函数def将以你想要lambda的方式捕获值 - 但嵌套可以防止你看到的问题

顺便说一下,在任何一个策略def make_button(n): def callback (_): self.showFloor(n) return cmds.button( label = 'floor '+ str(n), command = callback) for i in range(6): make_button(i) 中都需要额外的参数来容纳按钮总是触发的额外布尔值。

答案 1 :(得分:0)

OP在这里,以为我会发布我如何解决问题,以防它帮助其他人。 部分不是一个可行的选项,因为变量cmd(在示例中找到)仍然会使用循环更新,因此每个按钮仍然返回到最后一层。 在Maya中创建动态生成的UI的问题是它的UI命令是函数而不是类,这意味着您无法在命令中实际存储任何数据,只能传递它。幸运的是,有人已经走在我前面并将整个Maya的UI命令重写为类。您可以在此处找到该库:mGui

为此库编写的功能代码如下:

for i in range(0, numFloors):
    floor = i
    BTN= mGui.Button()
    BTN.data.[`floor`] = floor
    BTN.command = self.viewFloor

def viewFloor(self, defaultArg, **kw):
    floor = str(kw[`floor`])