繁体   English   中英

使用 Kivy 线程读取串行并同时获取用户输入

[英]Threading using Kivy to read serial and get user input at the same time

我正在制作一个 controller,它通过串行发送命令从真空泵连续更新标签。 这个 controller 还需要用户输入来启动和停止吸尘器。 我已经开始工作了,但是我的问题是时机似乎不对。 在程序开始时按钮是响应的,但是在运行几分钟后,schedule_interval() function 似乎压倒了基于序列号 output 的用户输入响应,并且按钮 output 显着滞后并且全部堆积在最后当我终止程序时。 (请注意,我正在使用 Raspberry Pi 发送串口。我不知道是否还需要考虑任何设备限制。)

Clock.max_iteration = 20

ser = serial.Serial()
ser.port = "/dev/ttyUSB0"
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
ser.timeout = 1            #non-block read
ser.xonxoff = False     #disable software flow control
ser.rtscts = False     #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False       #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 2     #timeout for write

Builder.load_file('MyApp.kv')

class MyLayout(Widget):

    def Button1(self):
        #read serial 
        #write serial 
        #update labels

    def Button2(self):
        #read serial 
        #write serial 
        #update labels

    def Button3(self):
        #read serial 
        #write serial 
        #update labels

    def exitButton(self):
        print("Program terminated")
        exit()


class MyApp(App):

    def build(self):
        return MyLayout()  
 

    def on_start(self):
        threading.Thread(target=self.updateLabels).start() #thread    
        #Clock.schedule_once(self.updateLabels, 1)
  
    
    def updateLabels(self, *args): #this function updates labels
        #write serial for label 1
        #read serial for label 1
        #update label 1 

        #write serial for label 2
        #read serial for label 2
        #update label 2

        #write serial for label 3
        #read serial for label 3
        #update label 3                
        Clock.schedule_interval(self.updateLabels, 2) #update labels every 2 seconds 


if __name__ == '__main__':
    try:
        ser.open()

    except Exception as e:
        print("error opening serial port: ") 
        exit()
    if ser.isOpen():
        try:
            ser.flushInput()
            ser.flushOutput()
        except Exception as e:    
            print("Error communication") + str(e)
    else: 
        print("Error communicating")
    MyApp().run()

Output 示例:

Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Write Command: Button1  
Write Command: Button2  #proceeds to lag after
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Write Command: Button2 #this button would have been pressed 30 sec ago
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Update Data: label1
Update Data: label2 
Update Data: label3 
Write Command: Button1 #piles up at the end after 3-5 mins unresponsive
Write Command: Button1  
Write Command: Button2  
Write Command: Button1  
Write Command: Button1  
Write Command: Button2  

Program terminated #takes at least 15 sec for this to actually terminate program

我尝试使用线程以允许两个函数同时运行。 但是,它们似乎干扰了其他人。 我的目标是让按钮在程序运行时随时响应,但标签每 2 秒或更短时间(如果可能)连续更新一次。

您的update_labels()方法应该在主线程上运行,而不是在另一个线程中运行,因为它正在修改 GUI。 一种解决方案是像这样修改on_start()方法:

def on_start(self):
    # threading.Thread(target=self.updateLabels).start() #thread    
    Clock.schedule_interval(self.updateLabels, 2)

这将每 2 秒在主线程上运行update_labels() 由于它处理调度,您可以消除任何使用Clock.schedule...在实际的update_labels()方法中。

如果您的update_labels()方法的内部花费太多时间,这种方法将干扰您的应用程序的响应能力。 如果是这种情况,那么您将需要在运行耗时代码但Labels未更新的另一个线程中运行不同的方法。 然后,该代码可以使用Clock.schedule_once()来安排一个只更改Label文本的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM