如何在Kivy的Label控件中每秒实时更新显示pyaudio采集的音频数据?
问题原因
你的代码问题根源是无限while True循环阻塞了Kivy的主线程。Kivy的所有UI渲染、属性更新逻辑都依赖主线程的事件循环调度,你把采集逻辑放在主线程的死循环里,事件循环完全没有机会执行界面重绘操作,只有当循环终止、主线程被释放后,最后一次的UI更新才会被渲染出来,就出现了你遇到的「运行时无显示、退出才出结果」的问题。
解决方法
推荐用「子线程跑音频采集+主线程更新UI」的方案,既不会阻塞界面,也能保证实时性:
1. 修改Python代码
首先导入Kivy的相关工具,把采集逻辑放到子线程执行,UI更新操作强制切回主线程:
# 先导入需要的依赖 from kivy.clock import mainthread from kivy.properties import StringProperty import threading # 你的Genereate类修改如下,继承类和你原有代码保持一致即可 class Genereate(Widget): # 注意:StringProperty必须定义为类属性,不能写在__init__方法里 pitchs1 = StringProperty("0") def pitches(self): # 启动守护子线程跑音频采集逻辑,不阻塞主线程 threading.Thread(target=self.audio_collect_loop, daemon=True).start() def audio_collect_loop(self): while True: data = stream.read(1024) samples = num.fromstring(data, dtype=aubio.float_type) pitch = pDetection(samples)[0] volume = num.sum(samples**2)/len(samples) volume = "{:.6f}".format(volume) print(pitch) print(volume) # 调用主线程方法更新UI self.update_ui(pitch, volume) if keyboard.is_pressed('1'): break # mainthread装饰器会强制该方法在Kivy主线程执行,保证UI更新合法 @mainthread def update_ui(self, pitch, volume): self.ids.volumes.text = volume self.pitchs1 = str(pitch)
2. kv代码无需调整
你原有kv代码的属性绑定逻辑是正确的,只需要确认两个Label的id没有拼写错误即可。如果需要严格控制每秒只刷新一次,在audio_collect_loop的循环里加time.sleep(1)即可。
内容的提问来源于stack exchange,提问作者Jefffly
相关产品推荐
相关产品推荐

