Kivy语言自动在属性中创建内部绑定。例如,如果我们将父级的位置分配给子级的位置,那么子级的位置将自动更新:
Widget:
Label:
pos: self.parent.pos
在这种情况下,如果我们移动父Widget
,那么孩子也将移动。如何解除孩子的财产pos
?我知道如何取消绑定(属性)[http://kivy.org/docs/api-kivy.uix.widget.html#using-properties]我自己绑定但如果我不知道如何取消绑定它们< strong>绑定方法的名称。
这是一个显示我的意思的小例子。 Button
向上将GridLayout
移至顶部,Down
移至底部。 Button
中心中心位于屏幕中间。我的问题是,当我点击向上或向下时,我的中心按钮就不再存在了。
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
上使用不断更新位置的动画。按钮的正常位置应该在gridlayout内,但偶尔会有一个按钮飞过屏幕并回到相同的位置。问题是,当我的gridlayout也在移动时,我无法让它们飞行,因为属性已被绑定,一旦按钮尝试飞行它就会返回到网格。这也意味着有时需要绑定。我想要的是控制绑定和解除绑定。
答案 0 :(得分:3)
评论现在似乎不起作用所以我会将其作为答案发布。
这是您使用这些修复程序的代码::
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绑定的属性,你可以使用内省来获取属性的list of observers。所以对于你的情况,它将是这样的东西::
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')))
您需要使用最新的master。虽然你需要重置kvlanguage中设置的绑定,但我要预先警告你要非常小心,但是你失去了kv语言的优势......只使用它如果你真的明白你在做什么。< / p>
答案 1 :(得分:0)
按照@ qua-non建议,我暂时将孩子移到另一位家长。它实际上解开它,或者可能将它重新绑定到新的父级。这是一个部分解决方案,因为无论什么原因,当我从GridLayout中取出它时(即当我按下回车键)并将其放入新的父级时,它不会自动更新位置。我需要在“开箱即用”按钮后按“向上”(或“向下”)。
然而,它确实会立即回归。当你第二次再次点击“开箱即用”按钮时,它会回到原来的位置。这部分很完美。并且它继续遵守其父母的指示。
换句话说,当我退出网格时它不会立即起作用,但是当我把它取回时它就会起作用。
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
float: _float
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"
FloatLayout:
id: _float
size_hint: None,None
""")
class Example(FloatLayout):
def centerize(self, instance):
if self.center_button.parent == self.center_widget:
self.center_widget.remove_widget(self.center_button)
self.float.add_widget(self.center_button)
self.float.size = self.center_button.size
self.float.x = self.center_button.x
self.float.center_y = self.center_y
else:
self.float.remove_widget(self.center_button)
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()
答案 2 :(得分:0)
这与我的尝试非常相似。不同之处在于我手动绑定了属性,因此我可以解除它们的绑定。基本上,如果我取消注释“开箱即用”按钮的行#pos: self.parent.pos
,那么我无法解除绑定,除非我将Button
分配给另一个父级为@ qua-non建议。
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
Builder.load_string("""
<Example>:
center_button: _center_button
GridLayout:
cols: 3
size_hint: .7, .3
pos_hint: {'center_x': .5}
Button:
on_press: self.parent.y = 0
text: "Down"
Widget:
Button:
id: _center_button
size: self.parent.size
#pos: self.parent.pos
on_press: root.centerize(*args)
text: "Out of the Grid"
Button:
on_press: self.parent.top = root.height
text: "Up"
""")
class Example(FloatLayout):
def __init__(self, **kwargs):
super(Example, self).__init__(**kwargs)
self.center_button.parent.bind(pos=self.binder)
self.centered = False
def binder(self, instance, value):
self.center_button.pos = instance.pos
def centerize(self, instance):
if self.centered:
self.center_button.parent.bind(pos=self.binder)
self.center_button.y = self.center_button.parent.y
self.centered = False
else:
self.center_button.parent.unbind(pos=self.binder)
self.center_button.center_y = self.height/2
self.centered = True
class ExampleApp(App):
def build(self):
return Example()
if __name__ == "__main__":
ExampleApp().run()