Python 使用回调使用类中的当前值运行函数

Python 使用回调使用类中的当前值运行函数,python,maya,Python,Maya,我很难想出一个好标题,所以我就在这里解释一下。我在Maya中使用Python,它有一些事件回调选项,因此您可以在保存时执行类似的操作:运行函数。我有一个用户界面类,我希望在触发某些事件时更新它,我可以这样做,但我正在寻找一种更干净的方法 下面是一个基本示例,与我的示例类似: class test(object): def __init__(self, x=0): self.x = x def run_this(self): print self.x

我很难想出一个好标题,所以我就在这里解释一下。我在Maya中使用Python,它有一些事件回调选项,因此您可以在保存时执行类似的操作:运行函数。我有一个用户界面类,我希望在触发某些事件时更新它,我可以这样做,但我正在寻找一种更干净的方法

下面是一个基本示例,与我的示例类似:

class test(object):
    def __init__(self, x=0):
        self.x = x
    def run_this(self):
        print self.x
    def display(self):
        print 'load user interface'

#Here's the main stuff that used to be just 'test().display()'
try:
    callbacks = [callback1, callback2, ...]
except NameError:
    pass
else:
    for i in callbacks:
        try:
            OpenMaya.MEventMessage.removeCallback(i)
        except RuntimeError:
            pass

ui = test(5)
callback1 = OpenMaya.MEventMessage.addEventCallback('SomeEvent', ui.run_this)
callback2 = OpenMaya.MEventMessage.addEventCallback('SomeOtherEvent', ui.run_this)
callback3 = ......
ui.display()
回调会一直持续到Maya重新启动,但如果将从
addEventCallback
返回的值传递给回调,则可以使用
removeCallback
将其删除。我目前的做法是在设置变量之前检查变量是否已设置,这比前面一行的
test().display()


有没有一种方法可以让我在函数中干净利落地完成它?如果我再次运行
测试
类或类似的东西,它会删除旧的吗?

有两种方法可以尝试

您可以拥有一个表示回调管理器的持久对象,并允许它钩住和解开自身

import maya.api.OpenMaya as om
import maya.cmds as cmds
om.MEventMessage.getEventNames()

class CallbackHandler(object):

    def __init__(self, cb, fn):
        self.callback = cb
        self.function  = fn
        self.id = None

    def install(self):
        if self.id:
            print "callback is currently installed"
            return False
        self.id = om.MEventMessage.addEventCallback(self.callback, self.function)
        return True

    def uninstall(self):
        if self.id:
            om.MEventMessage.removeCallback(self.id)
            self.id = None
            return True
        else:
            print "callback not currently installed"
            return False

    def __del__(self):
        self.uninstall()

def test_fn(arg):
    print "callback fired 2", arg

cb = CallbackHandler('NameChanged', test_fn)
cb.install()
# callback is active
cb.uninstall()
# callback not active
cb.install()
# callback on again
del(cb) # or cb = None
# callback gone again
在这个版本中,只要您希望回调持续存在,您就会存储您创建的回调处理程序,然后手动卸载它们,或者在不再需要它们时让它们脱离范围


另一种选择是创建自己的对象来表示回调,然后在自己的代码中添加或删除希望它触发的任何函数。这使管理完全站在您这边,而不是依赖api,api的好坏取决于您的需要。您将拥有一个可调用的
Event()
类(使用
\uuuu call\uuuu()
),它将有一个要启动的函数列表,然后Maya将调用它的“
\uuu call\uuuuuuu()
”。这里有一个您想要的事件处理程序对象类型的示例

,因此您永远不会希望注册多个回调来运行同一个函数(同时)?不,我希望对不同的事件有不同的回调,但每个事件只有一件事。多谢大家,这是一个非常好的主意,似乎效果很好,但还有一个简单的问题,除了
\uu del\uu
之外,有没有其他方法可以触发,即使
cb
被分配到不同的变量(为了安全起见)?如果窗口已经存在,部分用户界面会删除它,因此如果我将其设置为全局变量,那么这可能是添加代码的最佳位置。第二个选项虽然听起来有点棘手,但我的OpenMaya知识非常基础,因此我甚至不知道在没有它的情况下如何访问事件哈哈。我还注意到你使用了与导入稍有不同的是
maya.OpenMaya
maya.api.OpenMaya
几乎相同?
maya.api
导入“新”api,也称为“api2”。它更快、更容易使用,但比旧的更不完整。它是您应该使用的功能,除非您需要一个尚未迁移的函数。当对象超出范围时,会调用它。不幸的是,很难知道何时会发生这种情况,在我的测试用例中很容易,但在更复杂的系统中,您可以使用它ht不记得要清除它。您还可以创建一个scriptJob,在删除给定UI时触发,该UI将取消任何callbacksTo捆绑参数与回调脚本的挂钩。若要使用回调脚本,请尝试
functools.partial
或可调用对象。它的工作方式与所述的按钮脚本类似