Kivy框架中Label文本无法更新的技术求助
问题:Kivy界面Label文本无法随变量更新
问题描述
代码执行正常,但Kivy界面上的Label文本无法同步更新。data_PV变量初始值"toto"能正常显示,修改该变量后,Python的print输出显示变量已成功更新,但界面文本没有变化。
尝试方案
删除KV文件中text:root.data_PV语句,直接在Python代码中设置Label的text属性(已注释的两行代码),结果仍无法更新界面文本。
相关代码
Python代码
import ctypes import sys import time from kivy.config import Config Config.set('graphics','resizable', False) #S9 2960 x 1440 n = 3 Config.set('graphics','width', str(int(1440/n))) Config.set('graphics','height', str(int(2960/n))) import kivy from kivy.uix.popup import Popup from kivy.app import App, StringProperty from kivy.uix.label import Label from kivy.uix.gridlayout import GridLayout from kivy.uix.textinput import TextInput from kivy.uix.button import Button from kivy.uix.widget import Widget from kivy.uix.floatlayout import FloatLayout from kivy.uix.progressbar import ProgressBar from kivy.properties import ObjectProperty from kivy.properties import NumericProperty from kivy.clock import Clock from kivy.lang import Builder from kivy.uix.screenmanager import ScreenManager, Screen import paho.mqtt.client as mqtt import paho.mqtt.publish as publish import paho.mqtt.subscribe as subscribe import threading from kivy.clock import mainthread class MainWindow(Screen): pass class PompeSurf1Window(Screen): freq_SP = ObjectProperty(TextInput) data_PV = StringProperty("toto") def update(self, loc_data,*a): self.data_PV = str(loc_data) print("valeur data:", self.data_PV) #self.freq_SP.text= str(self.data_PV) #self.ids.label_freq_PV.text=self.data_PV def pub_freq_SP(self): for i in range(1): text = "at#rtuw=1,6,8193,"+str(int(self.freq_SP.text)*100) publish.single("set", text, qos=0, retain= False, hostname="test.mosquitto.org") class WindowManager(ScreenManager): pass kv = Builder.load_file('main.kv') class LoivesApp(App): client = mqtt.Client() @mainthread def on_message(self,client, userdata, message): data=message.payload.decode("utf-8") print(data) instance1 = PompeSurf1Window() instance1.update(data) def build(self): client = mqtt.Client() self.client.on_message=self.on_message self.client.connect('test.mosquitto.org',1883) self.client.loop_start() self.client.subscribe([("statusword2",0)]) return kv def on_pause(self): pass def on_resume(self): self.client.on_message=self.on_message self.client.connect('test.mosquitto.org',1883) self.client.loop_start() self.client.subscribe([("statusword2",0)]) if __name__ == "__main__": LoivesApp().run()
KV代码
WindowManager: MainWindow: PompeSurf1Window: <MainWindow>: name: "main" BoxLayout: orientation: "vertical" size: root.width, root.height spacing: 20 padding: 20 Label: text: "Ferme des Loives" font_size: 100 Button: text: "Pompe Surface 1" font_size: 50 size_hint: 0.8, 0.8 pos_hint: {"x":0.1, "top":0.9} on_release: app.root.current = "Pompe1" root.manager.transition.direction = "left" # peut être right up down <PompeSurf1Window>: name: "Pompe1" spacing: 20 padding: 20 freq_PV: label_freq_PV freq_SP: input_freq_SP GridLayout: resizable: False cols: 1 size: root.width, root.height spacing: 20 padding: 20 Label: size_hint_y: None height: 20 Label: text: "Pompe de Surface 1" font_size: 100 size_hint_y: None height: 50 GridLayout: cols: 2 Label: text: "Fréquence actuelle" font_size_hint: None font_size: 32 Label: text: "Consigne de fréquence" font_size_hint: None font_size: 32 Label: id: label_freq_PV text: root.data_PV font_size_hint: None font_size: 32 TextInput: id: input_freq_SP font_size: 32 multiline: False on_text_validate: root.pub_freq_SP() Button: text: "retour" size_hint: 0.8, 0.2 pos_hint: {"x":0.1, "top":0.9} on_release: app.root.current = "main" root.manager.transition.direction = "right"
解决方案
核心问题在于你在on_message回调中新建了一个PompeSurf1Window实例,而不是操作界面上已经存在的那个实例。KV文件中已经通过WindowManager创建了PompeSurf1Window的实例,你新创建的实例和界面显示的完全是两个对象,修改新实例的data_PV自然不会影响界面。
修改LoivesApp类中的on_message方法:
@mainthread def on_message(self,client, userdata, message): data=message.payload.decode("utf-8") print(data) # 替换新建实例的代码,获取屏幕管理器中已存在的PompeSurf1Window实例 instance1 = self.root.get_screen("Pompe1") instance1.update(data)
解释
self.root是App返回的WindowManager实例,调用get_screen("Pompe1")可以获取KV中定义的、当前管理的PompeSurf1Window实例。- 对这个实例调用
update方法修改data_PV,由于data_PV是StringProperty,会自动触发KV中text: root.data_PV的绑定更新,界面Label文本就会同步变化。 - 保留
@mainthread装饰器是正确的,因为MQTT回调运行在非主线程,Kivy的UI操作必须在主线程执行。
内容的提问来源于stack exchange,提问作者jmoupou
相关产品推荐
相关产品推荐

