首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何每半秒钟更新一次tkinter文本标签?如何避免.mainloop,使程序的其余部分可以执行?

如何每半秒钟更新一次tkinter文本标签?如何避免.mainloop,使程序的其余部分可以执行?
EN

Stack Overflow用户
提问于 2019-12-12 12:19:20
回答 1查看 179关注 0票数 0

我正在使用Kvaser Leaf Professional,并试图通过Python从摩托车中读取can总线数据,以便能够使用这些数据查看值的变化以及哪些值保持不变。

目前,我很难在tkinter上显示数据,并在每次数据再次读取/更新之后更新数据,因为它每隔几微秒就会改变一次。使用.after()的正常方式似乎不能100%起作用,或者我只是做错了什么。或者有比tkinter更好的显示更新数据的方法?

另一个问题是,当我显示tkinter时,它使用root.mailoop()运行窗口,当这种情况发生时,它进入主循环,不退出并运行程序的其余部分,也无法更新显示在窗口上的现有数据。有没有办法绕过root.mainloop()呢?

任何洞察力都将是有用的和/或我在代码中所犯的小错误。我是在两天前才开始使用Python的,现在我还在学习很多东西,还不知道所有的输入和输出。提前谢谢你。

到目前为止,这是我的全部计划:

代码语言:javascript
复制
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)

您可以根据需要编辑我的代码,如果我能够更好地实现代码,它将有很大帮助。

EN

回答 1

Stack Overflow用户

发布于 2019-12-12 15:19:02

你不需要使用多线程或任何复杂的东西。只需使用widget.after()方法,该方法在所需的时间之后调用您选择的另一个函数/方法。在下面的例子中,时间是1秒-> 1000毫秒。只需在call循环之前调用类,它就会开始工作。

代码语言:javascript
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59304444

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档