Python Kivy框架中不同布局类的通信实现方法
Kivy多布局通信实现方案
Kivy中跨布局交互不需要额外维护全局变量,最稳妥的方式是通过kv语言的id引用定位组件实例,顺着组件树即可拿到目标对象调用对应方法,实现点击按钮新增组件的需求。
第一步:修改kv文件,给目标组件绑定id
kv的id作用域和当前规则的根组件绑定,无法跨层级直接读取,需要给每层要访问的组件设置id,修改后的kv代码如下:
MainWidget: <Buttons_layout>: <Scroll_layout@ScrollView>: # 给内部的StackLayout绑定id,作用域属于Scroll_layout Buttons_layout: id: btn_container size_hint: 1,None height:self.minimum_height <MainWidget>: Button: text:'add' on_press: root.add_button() size_hint:None,1 width:dp(50) # 给Scroll_layout绑定id,作用域属于MainWidget Scroll_layout: id: scroll_area
第二步:修改Python端逻辑
把StackLayout新增按钮的逻辑封装在自身类里降低耦合,再在MainWidget的点击事件里通过id逐层拿到StackLayout实例,调用新增方法即可,修改后的main.py代码:
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.metrics import dp from kivy.uix.stacklayout import StackLayout class Buttons_layout(StackLayout): def __init__(self,**kwargs): super().__init__(**kwargs) self.number = 0 # 初始化加载5个默认按钮 for _ in range(5): self.add_new_btn() # 抽离新增按钮的公共方法,初始化和后续新增都复用同一段逻辑 def add_new_btn(self): self.number += 1 self.add_widget( Button( text=str(self.number), color=(200,100,100), size_hint=(0.2,None), height=dp(100) ) ) class MainWidget(BoxLayout): def __init__(self,**kwargs): super().__init__(**kwargs) def add_button(self): # 先拿到自身绑定的Scroll_layout实例,再拿到其内部的Buttons_layout实例 btn_stack = self.ids.scroll_area.ids.btn_container # 调用StackLayout自身的新增按钮方法 btn_stack.add_new_btn() class CanvosExampleApp(App): pass if __name__ == '__main__': CanvosExampleApp().run()
注意事项
- 不要用全局变量存储组件实例,多页面、多同名组件场景下很容易出现引用错乱的问题
- 如果组件嵌套层级极深,除了id逐层引用的方式,也可以通过
App.get_running_app().root拿到根组件后结合children属性遍历查找目标组件,但id引用是性能最高、逻辑最清晰、最不容易出错的方案 - 组件自身的操作(比如StackLayout添加自己的子按钮)尽量封装在组件类内部,不要让上层父组件直接操作深层子组件的内部属性,后续调整逻辑时不需要跨多个类修改代码
内容的提问来源于stack exchange,提问作者amir_hossain oroujlou
相关产品推荐
相关产品推荐

