如何取消绑定在 Kivy 语言中自动绑定的属性?
问题描述
Kivy 语言会自动在属性中创建内部绑定.例如,如果我们将 parent 的位置分配给 child 的位置,那么 child 的位置将自动更新:
The Kivy Language automatically creates internal binds in properties. For example, if we assign the position of the parent to the position of the child, then the position of the child is going to be updated automatically:
Widget:
Label:
pos: self.parent.pos
在这种情况下,如果我们移动父 Widget
,那么子也将移动.如何解除子属性 pos
的绑定?我知道如何解除绑定(属性)[http://kivy.org/docs/api-kivy.uix.widget.html#using-properties] 我绑定自己,但如果我不知道如何解除绑定它所绑定的方法的名称.
In this case, if we move the parent Widget
, then the child is also going to move. How do I unbind the property pos
from the child? I know how to unbind (properties)[http://kivy.org/docs/api-kivy.uix.widget.html#using-properties] that I bind myself but how do I unbind them if I don't know the name of the method it is bound.
这是一个小例子来说明我的意思.Button
Up 将 GridLayout
移动到顶部,将 Down
移动到 Bottom.Button
Center 位于屏幕中间.我的问题是,当我单击 Up 或 Down 时,我的居中按钮不再存在.
Here is a small example to show what I mean. The Button
Up moves the GridLayout
to the top and Down
to the Bottom. The Button
Center center itself in the middle of the screen. My problem is that when I click Up or Down my Centered button is not anymore.
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
上使用了一个不断更新位置的动画.按钮的正常位置应该在网格布局内,但有时其中一个按钮会飞过屏幕并返回到相同的位置.问题是,当我的网格布局也在移动时,我无法让它们飞行,因为属性已绑定,并且一旦按钮尝试飞行,它就会返回网格.这也意味着有时需要绑定.我想要的是控制绑定和解除绑定.
Why do I want to do that in any case? I am using an animations on the 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.
解决方案
评论现在似乎不起作用,所以我会发布这个作为答案.
Comments don't seem to be working right now so I'll post this as a answer.
- 您已经有一个 FloatLayout(您的根小部件).用那个代替创建一个新的 FloatLayout.
- 在从网格中删除小部件之前.
- 存储它的大小,
- 将 size_hint 设置为无、无
- 设置 pos_hint 以将小部件定位在中心.
这是您的代码,其中包含这些修复::
Here's your code with these fixes::
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 绑定的属性,您可以使用自省来获得 属性的观察者列表.所以对于你的情况,它会是这样的::
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::
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')))
您需要为此使用最新的主服务器.我应该预先警告您要非常小心,尽管您需要重置在 kvlanguage 中设置的绑定,但是您会失去 kv 语言的优势......只有在您真正了解自己在做什么时才使用它.
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.
相关文章