我有一个名为Widget
的Kivy MainPage
,它有一个子窗口小部件。这些子窗口小部件需要访问与其父级相同的消息调度程序(与Kivy的EventDispatcher
无关):
class MainPage(Widget):
def __init__(self, dispatcher):
self.child = ChildWidget(dispatcher)
self.add_widget(child1)
在.kv
文件中我定义了<ChildWidget>
的视觉属性,但我没有在<MainPage>
中指定它的位置。我希望<MainPage>
指定孩子应该如何定位。这样的事情可能吗?
<ChildWidget>:
...
<MainPage>:
self.child:
pos: (10, 10)
答案 0 :(得分:1)
假设ChildWidget仍然是Kivy Widget(继承自Widget或其子类)。
[使用kv的简单方法]
如果您希望孩子控制它所在的父母所在的位置,您可以做到::
<ChildWidget>
pos: (self.parent.x + 10, self.parent.y + 10) if self.parent else (100, 100)
用于控制孩子的位置,可以做到::
<MainPage>
on_children:
# reposition children
root.reposition_children(args[1])
on_size:
# reposition children when parents size changes
root.reposition_children(self.children)
on_pos:
# reposition children when widgets size changes
root.reposition_children(self.children)
你的.py中的
class MainPage(Widget):
...
...
def reposition_children(self, children):
for child in children:
child.pos = x, y
child.size = d, e
[更详细和完整的方式]
你基本上想要的是你的主要小工具表现得像Layout。此链接是代码,其中还包含内联文档。代码本身是一个抽象类,为您提供有关如何构建/设计布局的指导。
您应该从Layout类继承并在do_layout中进行小部件定位,通过self.trigger_layout调用它(这样小部件的定位会延迟到需要显示之前屏幕和触发器确保每帧不会多次调用该函数。)
您应bind trigger_layout使用children, size, pos...等属性,以便在这些属性发生变化时重新触发do_layout
。
答案 1 :(得分:1)
如果您的定位目标不是太复杂,RelativeLayout
就足够了。
class MainPage(RelativeLayout):
def __init__(self, dispatcher, **kwargs):
super(MainPage, self).__init__(**kwargs)
self.child = ChildWidget(dispatcher, pos=(10,10))
self.add_widget(self.child)
RelativeLayout
(通常任何布局 - 除了保持绝对定位的FloatLayout)都会使子项更新到父项的位置。所有布局都是小部件,所以你应该是安全的。
<ChildWidget>:
size_hint: .1, .05
text: "press me"
on_press: self.parent.pos = (200,200)
<MainPage>:
pos: 400,400
以下是我尝试的完整代码:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.button import Button
Builder.load_string("""
<ChildWidget>:
size_hint: .1, .05
text: "press me"
on_press: self.parent.pos = (200,200)
<MainPage>:
pos: 400,400
""")
class Dispatcher():
pass
class ChildWidget(Button):
def __init__(self, dispatcher, **kwargs):
super(ChildWidget, self).__init__(**kwargs)
self.dispatcher = dispatcher
class MainPage(RelativeLayout):
def __init__(self, dispatcher, **kwargs):
super(MainPage, self).__init__(**kwargs)
self.child = ChildWidget(dispatcher, pos=(10,10))
self.add_widget(self.child)
class TestApp(App):
def build(self):
dispatcher = Widget()
return MainPage(dispatcher)
if __name__ == '__main__':
TestApp().run()