bpy.app.timers.register(my_func)
未正确注册
我们在尝试时遇到错误
bpy.app.timers.unregister(my_func)
bpy.app.timers.unregister(clock)
ValueError: Error: function is not registered
我想运行计时器来更新view3d
ba_props.py
class BastromProps(PropertyGroup):
...
clock_interval: IntProperty(
name="",
description="update clock every x seconds",
default=1,
)
def register():
bpy.utils.register_class(BastromProps)
bpy.types.Scene.bapp = PointerProperty(type=BastromProps)
...
ba_ui.py
class EVENT_PT_two(Panel):
bl_idname = "EVENT_PT_one"
...
def draw(self, context):
layout = self.layout
bapp = context.scene.bapp
if bapp.run_clock_1_:
clock_icon = "PREVIEW_RANGE"
else:
clock_icon = "RECOVER_LAST"
split = layout.split(factor=0.6, align=True)
...
split.operator("event.two_clock", text="", icon=clock_icon)
ba_ops.py
class EVENT_OT_one_clock(Operator):
# event one 'run clock' button was pressed
def execute(self, context):
bapp = bpy.data.scenes["zodiac"].bapp
# update chart every x seconds
def update_interval():
# get local / computer utc timezone-aware datetime
local_utc_now = datetime.utcnow().replace(tzinfo=zi("UTC"))
...
return bapp.clock_interval
# toggle 'run clock' mode
if bapp.run_clock_1_:
bpy.app.timers.register(update_interval)
bapp.run_clock_1_ = False
else:
bpy.app.timers.unregister(update_interval)
bapp.run_clock_1_ = True
if bpy.app.timers.is_registered(update_interval):
print(
f"event.one_clock: timers.is_registered: {bpy.app.timers.is_registered}"
)
...
return {"FINISHED"}
上面的代码给出错误:
bpy.app.timers.unregister(update_interval)
ValueError: Error: function is not registered
我从网上尝试了一些结果,即:
将
update_interval(self)
移到 execute(...)
函数之外,然后:
clock = self.update_interval()
if bapp.run_clock_1_:
bpy.app.timers.register(clock)
bapp.run_clock_1_ = False
else:
bpy.app.timers.unregister(clock)
bapp.run_clock_1_ = True
仍然报错
我们如何修复代码才能正常运行?
(添加更多详细信息,否则我无法发布问题)
是的,你是对的,你必须将
update_interval
函数移到 execute
之外。
如果
update_interval
定义在 execute
内部,则每次运行操作符时都会创建 update_interval
的新实例。因此,当您尝试调用 bpy.app.timers.unregister(update_interval)
时,它总是会失败,因为它是不同的实例。
然后,如果您想在
clock_interval
函数内部使用 update_interval
属性,您可以:
def update_interval():
interval = bpy.context.scene.bapp.clock_interval
<...update logic...>
return interval
import functools
update_func = None
def update_interval(interval):
<...update logic...>
return interval
class EVENT_OT_one_clock(Operator):
def execute(self, context):
bapp = bpy.context.scene.bapp
global update_func
if bapp.run_clock_1_:
# store function in a variable so it can be unregistered later
update_func = functools.partial(update_interval, bapp.clock_interval)
bpy.app.timers.register(update_func)
<...other operator code...>
或者,如果您希望
update_interval
函数成为类的一部分,如您的示例所示:
时钟 = self.update_interval()
您需要使用
functools.partial
才能正确注册:
self.update_func = functools.partial(self.update_interval)
bpy.app.timers.register(self.update_func)
您还应该确保在尝试注销计时器之前始终检查计时器是否已注册,以便可以处理错误:
if bpy.app.timers.is_registered(update_func):
bpy.app.timers.unregister(update_func)
else:
print("error")
此外,要更改场景属性,您需要使用原始对象而不是副本。在您的代码中,
run_clock_1_
将始终为 false。
# this won't work
bapp = bpy.context.scene.bapp
bapp.run_clock_1_ = False
# this works
bpy.context.scene.bapp.run_clock_1_ = False