我有一个简单的项目,可从电位计和Arduino读取串行数据。获得转换后的读数后,该读数应该会更改空白窗口的颜色。
由于某些原因,我无法更新窗口,而且我真的不熟悉Tkinter。感谢您的任何投入。
import Tkinter
import serial
ser = serial.Serial("/dev/ttyACM0", 9600, timeout = 2)
def update():
while 1:
line = ser.readline()
color = "#%02x%02x%02x" %(000, 000, int(line))
return color
root = Tkinter.Tk()
root.geometry("500x500")
root.configure(background = update())
root.mainloop()
最佳答案
我最近只是这样做来监视来自串行设备的输入。准备就绪后,您需要能够接收串行数据,并保持Tk事件循环运行。您可以使用辅助线程读取串行数据并将输入发布到UI线程以进行显示,也可以使用Twisted框架。在我的情况下,我使用twisted来避免从串行端口进行任何阻塞读取,并仅使用画布线将值绘制为简单的线图。
#!/usr/bin/python
import sys
from Tkinter import *
from ttk import *
from twisted.internet import tksupport, reactor
from twisted.internet.serialport import SerialPort
from twisted.protocols import basic
class DeviceProtocol(basic.LineReceiver):
#delimiter = "\r\n" # default delimiter is crlf
def __init__(self, callback):
self.callback = callback
def lineReceived(self, data):
self.callback.OnDataReceived(data)
class MainWindow(Frame):
def __init__(self, parent, title):
self.data = [(n,1) for n in range(100)]
self.sample = len(self.data)
Frame.__init__(self, parent)
parent.wm_withdraw()
parent.wm_title(title)
self.CreateUI()
self.grid(sticky = (N,S,W,E))
parent.wm_protocol("WM_DELETE_WINDOW", self.onDestroy)
parent.grid_rowconfigure(0, weight = 1)
parent.grid_columnconfigure(0, weight = 1)
parent.wm_deiconify()
def CreateUI(self):
canvas = Canvas(self, background="white")
canvas.create_line((0, 0, 1, 1), tag='Plot', fill='red', smooth=True)
canvas.grid(sticky = (N,S,W,E))
self.canvas = canvas
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
def onDestroy(self):
reactor.stop() # required to cleanly shutdown twisted event loop
def Monitor(self, port, baudrate = 9600):
self.serial = SerialPort(DeviceProtocol(self),
port, reactor, baudrate=baudrate)
def OnDataReceived(self, data):
print data
for v in data.split():
self.data.append((self.sample, int(v)))
self.sample += 1
if len(self.data) > 100:
self.data = self.data[-100:]
self.after_idle(self.OnUpdatePlot)
def OnUpdatePlot(self):
width = self.canvas.winfo_width()
height = self.canvas.winfo_height()
xS,yS = self.data[0]
xE,yE = self.data[-1]
coords = []
fx = width / (xE - xS)
fy = height / 100 # y values are 0 < y < 100
for (x,y) in self.data:
coords.append(fx * (x - xS))
coords.append(fy * (100 - y))
self.canvas.coords('Plot', *coords)
def main(argv = None):
if argv is None:
argv = sys.argv
if len(argv) != 2:
print "usage: plot_serial <serialport>"
return 1
root = Tk()
tksupport.install(root) # register the Tk event loop with twisted
main = MainWindow(root, "Plot serial data")
main.Monitor(argv[1])
reactor.run() # use twisted instead of root.mainloop()
return 0
if __name__ == '__main__':
sys.exit(main())