【问题标题】:Maya/Python: Creating Unique Commands in Loop-Generated UIMaya/Python:在循环生成的 UI 中创建独特的命令
【发布时间】:2018-01-05 20:00:27
【问题描述】:

在 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。就像我说的,我知道为什么会发生这种情况,这段代码 sn-p 只是我创建一个可以传达我正在尝试做的事情的 sn-p 代码的最佳机会。不幸的是,我不知道如何真正做到这一点。

我的一些想法是:

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

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

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

【问题讨论】:

    标签: python loops user-interface maya autodesk


    【解决方案1】:

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

    您可以通过以下几种方式解决它:

    使用 functools.partial 代替 lambda

    functools.partial 是来自functools 模块的对象,它将可调用对象和参数绑定在一起。你几乎可以像使用 lambda 一样使用它:

    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 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)
    

    这里的嵌套函数 def 将以您希望 lambda 的相同方式捕获值 - 但嵌套可以防止您看到的问题

    顺便说一句,self.showFloor 在任一策略中都需要一个额外的参数来适应按钮总是触发的额外布尔值。

    【讨论】:

      【解决方案2】:

      在这里,我想我会发布我是如何解决问题的,以防它帮助其他人。 Partial 不是一个可行的选项,因为变量 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`])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-06
        • 2021-01-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多