【发布时间】:2016-03-16 00:13:55
【问题描述】:
我有一个应用程序通过某个服务器充当另一个应用程序的 UI。将有多个 UI 应用程序实例。 UI 应用程序有一个属性n_property,表示远程应用程序的一个参数。当n_property通过UI改变时,它被发送到服务器——这里通过send_value模拟。服务器将其传递给要控制的应用程序,在那里得到验证,然后传回服务器。服务器将新值发送回 UI(以及其他已连接的 UI 实例),此处使用 receive_value 进行模拟。
我想将n_property(以及代表它的Slider)设置为新值而不触发新的n_property 事件,因为我不想进入无限循环改变值,当滑块拖动得足够快时就会发生这种情况。
在其他框架中,我会在 receive_value 中使 on change 事件静音,但我还没有在 kivy 中找到一种优雅的方式来做到这一点[1]。
这是一个示例程序:
from kivy.lang import Builder
from kivy.app import App
from kivy.properties import BoundedNumericProperty
from kivy.clock import Clock
class PropApp(App):
n_property = BoundedNumericProperty(5, min=0, max=10)
def build(self):
rw = Builder.load_string("""
GridLayout:
cols:2
Label:
text: "Property Value"
Label:
id: prop_label
text: str(app.n_property)
Label:
text: "Control"
Slider:
id: prop_slider
min: 0
max: 10
value: app.n_property
""")
self.bind(n_property=rw.ids.prop_slider.setter('value'))
rw.ids.prop_slider.bind(value=self.setter('n_property'))
self.bind(n_property=self.send_value)
return rw
def send_value(self, inst, val):
print self.n_property
Clock.schedule_once(lambda dt: self.receive_value(val), .02)
def receive_value(self, val):
self.n_property = val
if __name__ == '__main__':
PropApp().run()
编辑:
根据文档,一旦处理程序返回True,事件分派就会停止,并且处理程序会以与附件相反的顺序被调用。
所以我想把receive_value改成
def receive_value(self, val):
print "Old value: {} new value: {}".format(self.n_property, val)
def swallow(inst, val):
print "Got swallowed {}".format(val)
inst.funbind('n_property', swallow)
return True
self.fbind('n_property', swallow)
self.n_property = val
这将是一个聪明的方法来实现这一点,虽然是的,我似乎无法进入无限循环,但仍有一些“反弹”。
似乎确实,存储回调的EventObservers 在Property 的定义中使用dispatch_reverse=0 初始化,但对于使用register_event_type 注册的事件,它是dispatch_reverse=1。
[1] 我想我可以有一个属性
_n_property,并使n_property 一个AliasProperty 其setter 和getter 访问_n_property。但这不是Property 的不同子类的通用解决方案(即必须单独处理BoundedNumericPropery 或OptionProperty 的边界检查)。
【问题讨论】:
标签: python events event-handling kivy