如何取消绑定用Kivy语言自动绑定的属性? [英] How to unbind a property automatically binded in Kivy language?
问题描述
Kivy语言会自动在属性中创建内部绑定.例如,如果我们将父级的位置分配给子级的位置,那么子级的位置将自动更新:
Widget:
Label:
pos: self.parent.pos
在这种情况下,如果我们移动父级Widget
,则子级也将移动.我如何从子级取消绑定属性pos
?我知道如何解除绑定(属性)[http://kivy.org/docs/api-kivy.uix.widget.html#using-properties]绑定自己的身份,但是如果我不知道如何<绑定方法的名称.
这里有一个小例子来说明我的意思. Button
上将GridLayout
移至顶部,将Down
移至底部. Button
Center (中心)位于屏幕中央.我的问题是,当我单击向上或向下时,居中"按钮不再存在.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
Builder.load_string("""
<Example>:
GridLayout:
id: _box
cols: 3
size_hint: .7, .3
pos_hint: {'center_x': .5}
x: 0
Widget:
Button:
pos: self.parent.pos
size: self.parent.size
on_press: _box.y = 0
text: "Down"
Widget:
Button:
pos: self.parent.pos
size: self.parent.size
on_press: self.center_y = root.height/2
text: "Out of the Grid"
Widget:
Button:
pos: self.parent.pos
size: self.parent.size
on_press: _box.top = root.height
text: "Up"
""")
class Example(FloatLayout):
pass
class ExampleApp(App):
def build(self):
return Example()
if __name__ == "__main__":
ExampleApp().run()
无论如何我为什么要这样做?我正在GridLayout
上使用不断更新位置的动画.按钮的正常位置应在网格布局内,但有时按钮之一会飞过屏幕并返回相同位置.问题是我无法在我的网格布局也移动的同时使它们飞行,因为该属性已绑定,并且一旦尝试飞行的按钮将立即返回到网格.这也意味着绑定有时是理想的.我想要的是控制绑定和取消绑定.
评论现在似乎无效,因此我将其发布为答案.
- 您已经有一个FloatLayout(您的根窗口小部件).用它代替 创建一个新的FloatLayout.
- 从网格中删除窗口小部件之前.
- 存储它的大小,
- 将size_hint设置为无,无"
- 设置pos_hint将小部件放置在中心位置.
- 将小部件添加到网格时,请执行相反的操作.
这是包含以下修复程序的代码:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
Builder.load_string("""
<Example>:
center_button: _center_button
center_widget: _center_widget
grid:_grid
GridLayout:
id: _grid
cols: 3
size_hint: .7, .3
pos_hint: {'center_x': .5}
x: 0
Widget:
Button:
pos: self.parent.pos
size: self.parent.size
on_press: _grid.y = 0
text: "Down"
Widget:
id: _center_widget
Button:
id: _center_button
pos: self.parent.pos
size: self.parent.size
on_press: root.centerize(*args)
text: "Out of the Grid"
Widget:
Button:
pos: self.parent.pos
size: self.parent.size
on_press: _grid.top = root.height
text: "Up"
""")
class Example(FloatLayout):
def centerize(self, instance):
if self.center_button.parent == self.center_widget:
_size = self.center_button.size
self.center_widget.remove_widget(self.center_button)
self.center_button.size_hint = (None, None)
self.add_widget(self.center_button)
self.center_button.pos_hint = {'center_x': .5, 'center_y':.5}
else:
self.remove_widget(self.center_button)
self.center_button.size_hint = (1, 1)
self.center_widget.add_widget(self.center_button)
self.center_button.size = self.center_widget.size
self.center_button.pos = self.center_widget.pos
class ExampleApp(App):
def build(self):
return Example()
if __name__ == "__main__":
ExampleApp().run()
更新1:
如果出于任何原因仍然需要取消绑定kvlang的属性,则可以使用自省来获取
Why do I want to do that in any case? I am using an animations on the Comments don't seem to be working right now so I'll post this as a answer. Here's your code with these fixes:: Update 1: If for whatever reason you still need to unbind the properties bound by kvlang you can do so using introspection to get a list of observers for the property. so for your case it would be something like this:: You would need to use the latest master for this. I should fore-warn you to be extremely careful with this though you'd need to reset the bindings set in kvlanguage, but then you loose the advantage of kv language... Only use this If you really understand what you are doing. 这篇关于如何取消绑定用Kivy语言自动绑定的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
GridLayout
that constantly updates the position. The normal position of the buttons should be inside the gridlayout but once in a while one of the buttons flies over the screen and come back to the same position. The problem is that I cannot make them fly while my gridlayout is also moving because the property is bound and as soon as the button try to fly it goes back to the grid. That also means that the binding is sometimes desirable. What I want is have control of the bind and unbind.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
Builder.load_string("""
<Example>:
center_button: _center_button
center_widget: _center_widget
grid:_grid
GridLayout:
id: _grid
cols: 3
size_hint: .7, .3
pos_hint: {'center_x': .5}
x: 0
Widget:
Button:
pos: self.parent.pos
size: self.parent.size
on_press: _grid.y = 0
text: "Down"
Widget:
id: _center_widget
Button:
id: _center_button
pos: self.parent.pos
size: self.parent.size
on_press: root.centerize(*args)
text: "Out of the Grid"
Widget:
Button:
pos: self.parent.pos
size: self.parent.size
on_press: _grid.top = root.height
text: "Up"
""")
class Example(FloatLayout):
def centerize(self, instance):
if self.center_button.parent == self.center_widget:
_size = self.center_button.size
self.center_widget.remove_widget(self.center_button)
self.center_button.size_hint = (None, None)
self.add_widget(self.center_button)
self.center_button.pos_hint = {'center_x': .5, 'center_y':.5}
else:
self.remove_widget(self.center_button)
self.center_button.size_hint = (1, 1)
self.center_widget.add_widget(self.center_button)
self.center_button.size = self.center_widget.size
self.center_button.pos = self.center_widget.pos
class ExampleApp(App):
def build(self):
return Example()
if __name__ == "__main__":
ExampleApp().run()
observers = self.center_widget.get_property_observers('pos')
print('list of observers before unbinding: {}'.format(observers))
for observer in observers:
self.center_widget.unbind(pos=observer)
print('list of observers after unbinding: {}'.format(self.center_widget.get_property_observers('pos')))