Kivy框架下Button的on_press绑定函数仅首次执行生效问题
问题原因
你的刷新功能失效核心是两个逻辑错误:
- 旧组件删除目标找错
你写的删除逻辑是遍历self.children(即MainScreen的直接子组件)查找ScrollView移除,但实际你每次生成的新ScrollView都是添加到self.ids.grids(id为grids的GridLayout)内部,ScrollView根本不是MainScreen的直接子组件,这段删除代码从第一次运行就没生效过。
第一次运行能正常显示,是因为初始状态下grids里只有顶部搜索栏,第一个ScrollView加进去刚好排在搜索栏下方可视区域内;第二次触发搜索时,旧的ScrollView没有被移除,你又往grids里叠加了新的ScrollView,受GridLayout布局规则和你写的固定尺寸影响,新ScrollView直接被挤出可视范围,看起来就像界面完全没更新。 - ScrollView尺寸设置不合理
你给ScrollView写的size = (Window.width, Window.height)是硬编码固定值,既没有绑定窗口尺寸变化事件,也没有适配父容器的实际可用高度,很容易出现组件超出布局边界、无法正常显示的问题。
修复方案
最小修改版
只需要调整Python端refresh函数的遍历目标,同时修正ScrollView的尺寸参数即可:
def refresh(self, tags): # 遍历grids布局的子组件,删除旧的ScrollView for c in list(self.ids.grids.children): if isinstance(c, ScrollView): self.ids.grids.remove_widget(c) tags = tags.lower() docs = db.collection('objects').where('type', '==', tags).stream() layout = GridLayout(cols = 1, spacing = 5, size_hint_y = None) layout.bind(minimum_height = layout.setter('height')) for doc in docs: button = RoundedButton(text = doc.get('specificType'), size_hint_y = None, height = 100) layout.add_widget(button) # ScrollView尺寸改为自适应父容器剩余空间 root = ScrollView(size_hint = (1, 1)) root.add_widget(layout) self.ids.grids.add_widget(root)
更稳定的优化版
不需要每次刷新都重复创建、删除ScrollView,直接在kv里提前定义好ScrollView和内部按钮容器,刷新时只需要清空旧按钮、添加新按钮即可,性能更好也不容易出布局问题:
修改kv代码,在grids布局里提前写好固定的ScrollView结构:
<MainScreen>: canvas.before: Color: rgba: (245/255,245/255,245/255,245/255) Rectangle: pos: self.pos size: self.size GridLayout: cols:1 spacing:5 size_hint_y:1 id: grids GridLayout: id: box cols:2 size_hint_y: None height:30 TextInput: id: ti hint_text: 'Search' size_hint: 1, None height:30 background_normal: '' Button: text: 'search' size_hint_x: 0.1 height:30 on_press: root.refresh(root.ids.ti.text) # 固定的滚动区域,不需要动态增删 ScrollView: id: scroll_area size_hint: (1,1) GridLayout: id: btn_container cols: 1 spacing: 5 size_hint_y: None height: self.minimum_height
对应简化后的refresh函数:
def refresh(self, tags): # 清空旧按钮 self.ids.btn_container.clear_widgets() tags = tags.lower() docs = db.collection('objects').where('type', '==', tags).stream() for doc in docs: button = RoundedButton(text = doc.get('specificType'), size_hint_y = None, height = 100) self.ids.btn_container.add_widget(button)
内容的提问来源于stack exchange,提问作者Croampers
相关产品推荐
相关产品推荐

