KivyGUI在发送重复命令时冻结

2024-06-16 10:46:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下代码,其中我试图将时间发送到Arduino,以便在OLED上显示。Arduino端工作正常,如果单独发送命令,它将显示。但是,我希望每秒钟更新一次时间。通过一些调整,我可以让它每2秒左右更新一次,有时一次显示两次。我尝试使用线程,但我不确定它是否正确。 以下是python脚本:

    import serial
    import kivy
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.widget import Widget
    from datetime import datetime, timedelta
    import time
    from kivy.clock import Clock
    import threading
    
    ard_connected = False
    
    try:
        ard = serial.Serial(
        port='COM10',
        baudrate = 9600
        )
        ard.flush()
        ard_connected = True
    except:
        print("Arduino Not Connected")
    
    Builder.load_file('Layout.kv')
    
    
    class GUILayout(Widget):
        def ShowTime(self, state):
            threading.Timer(1, self.ShowTime).start()
            now = datetime.now()
            a = timedelta(seconds=1)
            while state == 'down':
                if (ard_connected):
                    current_time = now.strftime("%H:%M:%S")
                    ard.write(current_time.encode())
                    ard.flush()
                    now += a
    
            if (ard_connected):
                ard.write(" ".encode())
                ard.flush()
    
    class GUI(App):
        def build(self):
            updateClock = GUILayout()
            Clock.schedule_interval(updateClock.ShowTime, 0.5)
            return updateClock
    
    if __name__ == '__main__':
        GUI().run()

和.kv文件:

    <GUILayout>
    BoxLayout:
        orientation: "vertical"
        size: root.width, root.height
            
        GridLayout:
            cols: 2
    
            ToggleButton:
                text: "Time"
                on_state: root.ShowTime(self.state)
                backgrund_normal: ""
                background_color: (150/255,150/255,150/255,1)

Tags: fromimportselfdatetimeiftimenowarduino
1条回答
网友
1楼 · 发布于 2024-06-16 10:46:16

启动ShowTime()方法时有太多内容:

Clock.schedule_interval(updateClock.ShowTime, 0.5)

on_state: root.ShowTime(self.state)

threading.Timer(1, self.ShowTime).start()

而且每一个都有可能启动一个无限循环(while state == 'down':),因为传递到ShowTime()state变量永远不会改变。单击ToggleButton开始的循环将在主线程中运行,冻结GUI

我认为更好的方法是在一个位置启动/停止ShowTime()方法。也许使用ToggleButton

尝试更改kv以实现以下目标:

        ToggleButton:
            text: "Time"
            on_state: root.startShowTime(self.state) if self.state == 'down' else root.stopShowTime()
            backgrund_normal: ""
            background_color: (150/255,150/255,150/255,1)

并添加/更改GUILayoutGUI方法以支持:

class GUILayout(Widget):
    def startShowTime(self, state):
        self.clock_event = Clock.schedule_interval(self.ShowTime, 0.5)

    def stopShowTime(self):
        self.clock_event.cancel()
        if (ard_connected):
            ard.write(" ".encode())
            ard.flush()

    def ShowTime(self, dt):
        if (ard_connected):
            now = datetime.now()
            current_time = now.strftime("%H:%M:%S")
            ard.write(current_time.encode())
            ard.flush()

class GUI(App):
    def build(self):
        updateClock = GUILayout()
        return updateClock

相关问题 更多 >