我正在使用Kvaser Leaf Professional
,并尝试通过 Python编码从摩托车读取 can-bus 数据,以便能够使用这些数据来查看哪些值更改,哪些值保持不变。
此刻,我正努力在tkinter
上显示数据,并在每次读取/更新数据后都对其进行更新,因为它每隔几微秒就会变化一次。正常使用.after()
的方法似乎无法100%正常工作,或者我只是做错了什么。还是有比tkinter
更好的显示更新数据的方法?
我遇到的另一个问题是,当我显示tkinter
时,它使用root.mailoop()
来运行窗口,当它发生时,它将进入该主循环,而不会退出并运行其余部分程序,也将无法更新窗口上显示的现有数据。有没有办法绕过root.mainloop()
?
任何见解都会有所帮助和/或我在代码中犯的小错误。我仅在两天前才开始使用Python,但我仍然学到很多东西,并且还不了解所有内容。 预先谢谢你。
到目前为止,这是我的整个程序:
import keyboard
import time
import sys
import tkinter as tk
import binascii
from canlib import canlib, Frame
from canlib.canlib import ChannelData
root = tk.Tk()
def setUpChannel(channel,
openFlags=canlib.canOPEN_ACCEPT_VIRTUAL,
bitrate=canlib.canBITRATE_500K,
bitrateFlags=canlib.canDRIVER_NORMAL):
ch = canlib.openChannel(channel, openFlags)
print("Using channel: %s, EAN: %s" % (ChannelData(channel).channel_name,
ChannelData(channel).card_upc_no)
)
ch.setBusOutputControl(bitrateFlags)
ch.setBusParams(bitrate)
ch.busOn()
return ch
def tearDownChannel(ch):
ch.busOff()
ch.close()
def text(t):
tx = binascii.hexlify(t).decode('utf-8')
n = 2
txt = [tx[i:i+n] for i in range(0, len(tx), n)]
return txt
def counter():
while True:
try:
cnt = 1
frame = ch0.read()
firstID = frame.id
while True:
frame = ch0.read()
cnt += 1
if frame.id == firstID:
break
pass
except (canlib.canNoMsg):
break
except (canlib.canError):
print("Rerun")
pass
return cnt
print("canlib version:", canlib.dllversion())
ch0 = setUpChannel(channel=0)
ch1 = setUpChannel(channel=1)
frame = Frame(id_=100, data=[1, 2, 3, 4], flags=canlib.canMSG_EXT)
ch1.write(frame)
print(frame)
cnt = counter()
print("Counter: %d" %(cnt))
time.sleep(1)
while True:
while True:
try:
show = ""
i = 1
while i <= cnt:
frame = ch0.read()
show = show +("%s\t%s\n" %(frame.id, text(frame.data)))
i += 1
print(show)
T = tk.Text(root, height=6, width=80)
T.config(state="normal")
T.insert(tk.INSERT, show)
T.pack()
root.mainloop()
break
except (canlib.canNoMsg) as ex:
pass
except (canlib.canError) as ex:
print(ex)
pass
tearDownChannel(ch0)
tearDownChannel(ch1)
您可以根据需要编辑我的代码,如果我能更好地实现代码,这将对您大有帮助。
答案 0 :(得分:0)
您不需要使用多线程或任何令人费解的东西。只需使用widget.after()方法在所需时间后调用您选择的另一个函数/方法即可。在以下情况下,时间为1秒-> 1000毫秒。只需在mainloop之前调用该类,它将开始工作。
class UI:
def __init__(self, parent):
# variable storing time
self.seconds = 0
# label displaying time
self.label.configure(text="%i s" % self.seconds)
# start the timer
self.label.after(1000, self.refresh_label)
def refresh_label(self):
#refresh the content of the label every second
# increment the time
self.seconds += 1
# display the new time
self.label.configure(text="%i s" % self.seconds)
# request tkinter to call self.refresh after 1s (the delay is given in ms)
self.label.after(1000, self.refresh_label)