7

how can i use while loop in this code to read serial every 2 second and show it in a Label? this application will hanged in run and i'm new to python to solve this.

from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from time import sleep
import serial


class LoginScreen(GridLayout):
  def __init__(self, **kwargs):
    super(LoginScreen, self).__init__(**kwargs)
    self.cols = 2
    self.rows = 2
    ser = serial.Serial('COM3', 9600, timeout=0)
    while 1:
        sleep(2)
        ser.read()
        data = ser.read()
        self.add_widget(Label(text=str(data)))


class MyApp(App):
  def build(self):
    return LoginScreen()


if __name__ == '__main__':
  MyApp().run()
pneumatics
  • 2,836
  • 1
  • 27
  • 27
A.M
  • 345
  • 4
  • 13

1 Answers1

3

You can't run a 'while True' loop like that - that's what Kivy itself is doing internally, every iteration it checks input, updates the gui etc. By doing it yourself you stop Kivy's loop from ever advancing. This isn't just a kivy thing either, it's also how other gui frameworks work, though not all run the gui stuff in the main thread.

The sleep also does the same thing - any time you sleep, it does exactly that, and the gui will freeze until it finishes.

The solution is to hook into Kivy's event system and use its internal while loop. The simplest way is probably to add a new method to your LoginScreen, as below.

in __init__:

self.ser = serial.Serial('COM3', 9600, timeout=0)

and a new method:

def update(self, dt):
    self.ser.read()  # Not sure if you're deliberately or accidentally reading twice
    data = self.ser.read()
    self.add_widget(Label(text=str(data)))    

...and then

from kivy.clock import Clock
from functools import partial
Clock.schedule_interval(self.update, 2)

The update method will then be called every 2 seconds.

inclement
  • 29,124
  • 4
  • 48
  • 60