在Kivy的Clock.schedule_interval中使用STATE控制UI不生效该如何解决?
问题分析与解决方案
你原本的STATE控制方案不可行,核心原因有两个:
build()方法仅在应用初始化启动时执行1次,后续修改全局state变量不会重新触发界面渲染,你写在build里的if state == 0判断逻辑只会在启动时跑一次,不会动态响应state变化- 你在
calculate方法中写的state = 1是方法内的局部变量,根本没有修改你声明的全局state变量,就算加上global state声明修改成功也达不到效果,因为build早就执行完成了
正确实现方式
你不需要额外定义state变量,直接操作布局对象移除不需要的控件即可,修改后的代码如下:
from kivymd.app import MDApp from kivymd.uix.textfield import MDTextField from kivymd.uix.label import MDLabel from kivymd.uix.button import MDRectangleFlatButton from kivy.uix.boxlayout import BoxLayout from kivy.core.window import Window from kivy.clock import Clock # 修正原代码错误的Clock导入路径 Window.size = (350,350) class MainApp(MDApp): def build(self): # 将布局存为实例属性,方便后续操作 self.layout = BoxLayout(orientation='vertical', spacing=30, padding=10) self.theme_cls.primary_palette='Green' self.balance = MDTextField(hint_text="初始余额", pos_hint={'center_x':0.5, 'center_y':0.5}, size_hint=(None,None), width = 180) self.increment = MDTextField(hint_text="增量值", pos_hint={'center_x':0.5, 'center_y':0.5}, size_hint=(None,None), width = 180) self.button = MDRectangleFlatButton(text='Submit', pos_hint={'center_x':0.5, 'center_y':0.5}, on_release = self.release) self.result = MDLabel() self.layout.add_widget(self.balance) self.layout.add_widget(self.increment) self.layout.add_widget(self.button) self.layout.add_widget(self.result) return self.layout def release(self, obj): # 输入合法性校验 try: self.position = int(self.balance.text) self.inc_val = int(self.increment.text) except ValueError: self.result.text = "请输入合法的数字" return # 直接移除不需要的控件 self.layout.remove_widget(self.balance) self.layout.remove_widget(self.increment) self.layout.remove_widget(self.button) # 启动定时任务 Clock.schedule_interval(self.calculate, 1) def calculate(self, dt): self.position += self.inc_val self.result.text = 'Result is : ' + str(self.position) if __name__ == '__main__': MainApp().run()
核心修改点说明
- 修正了Clock的导入路径,原代码中
from kivy.properties import Clock是错误的,Clock属于kivy.clock模块 - 将根布局BoxLayout存为实例属性
self.layout,可以在其他方法中直接操作布局中的控件 - 移除了无用的全局state变量,在提交按钮触发的release方法中直接做输入校验,校验通过后直接移除不需要的输入框和按钮控件,一步达到你要的效果
- 提前把输入的余额和增量转成int类型存储,不需要每次计算都做类型转换,也避免了后续输入框被删除后读取不到值的问题
内容的提问来源于stack exchange,提问作者Kevin Foster
相关产品推荐
相关产品推荐

