Dynamically updating Tkinter window based on serial data

后端 未结 2 2036
悲&欢浪女
悲&欢浪女 2020-12-05 21:47

I\'m trying to write a program that gets data from a serial port connection and automatically updates the Tkinter window in real time based on that data.

I tried to

相关标签:
2条回答
  • 2020-12-05 22:27

    You need to put the GUI in the main thread, and use a separate thread to poll the serial port. When you read data off of the serial port you can push it onto a Queue object.

    In the main GUI thread you can set up polling to check the queue periodically, by using after to schedule the polling. Call a function which drains the queue and then calls itself with after to effectively emulate an infinite loop.

    If the data that comes from the sensor comes at a fairly slow rate, and you can poll the serial port without blocking, you can do that all in the main thread -- instead of pushing and pulling from the queue, your main thread can just see if there's data available and read it if there is. You can only do this if it's possible to read without blocking, otherwise your GUI will freeze while it waits for data.

    For example, you could make it work like this:

    def poll_serial_port(self):
        if serial.has_data():
            data = serial.readline()
            self.lbl.configure(text=data)
        self.after(100, self.poll_serial_port)
    

    The above will check the serial port 10 times per second, pulling one item off at a time. You'll have to adjust that for your actual data conditions of course. This assumes that you have some method like has_data that can return True if and only if a read won't block.

    0 讨论(0)
  • 2020-12-05 22:45

    Don't run the TK gui from a thread - run it from the main process. I mashed your example into something that demonstrates the principle

    from time import sleep
    import threading
    from Tkinter import *
    
    serialdata = []
    data = True
    
    class SensorThread(threading.Thread):
        def run(self):
            try:
                i = 0
                while True:
                    serialdata.append("Hello %d" % i)
                    i += 1
                    sleep(1)
            except KeyboardInterrupt:
                exit()
    
    class Gui(object):
        def __init__(self):
            self.root = Tk()
            self.lbl = Label(self.root, text="")
            self.updateGUI()
            self.readSensor()
    
        def run(self):
            self.lbl.pack()
            self.lbl.after(1000, self.updateGUI)
            self.root.mainloop()
    
        def updateGUI(self):
            msg = "Data is True" if data else "Data is False"
            self.lbl["text"] = msg
            self.root.update()
            self.lbl.after(1000, self.updateGUI)
    
        def readSensor(self):
            self.lbl["text"] = serialdata[-1]
            self.root.update()
            self.root.after(527, self.readSensor)
    
    if __name__ == "__main__":
        SensorThread().start()
        Gui().run()
    
    0 讨论(0)
提交回复
热议问题