简体   繁体   中英

tkinter overhead update label text

import tkinter as tk  
import time

class Example(tk.Toplevel):

    def __init__(self, root):
        tk.Toplevel.__init__(self, root)
        self.canvas = tk.Canvas(self, borderwidth=0, background="#ffffff")
        self.frame = tk.Frame(self.canvas, background="#ffffff")
        self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")

        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas.create_window((4,4), window=self.frame, anchor="nw", 
                              tags="self.frame")

        self.frame.bind("<Configure>", self.onFrameConfigure)

        self.populate()

        self.l= tk.Label(self.frame, text= 1)
        self.l.grid()
        self.cb= tk.Button(self.frame, text= "asdf", command= self.cnt)
        self.cb.grid()
    def cnt(self):
        slowlist= []
        slow= 0
        for x in range(10000):
            now= time.time()
            self.l["text"]+=1
            end= time.time()
            if end-now >= 0.001:
                slow+=1
                slowlist.append(end-now)
        print (slow)
        print (slowlist[:5])

    def populate(self):
        '''Put in some fake data'''
        for row in range(100):
            tk.Label(self.frame, text="%s" % row, width=3, borderwidth="1", 
                 relief="solid").grid(row=row, column=0)
            t="this is the second column for row %s" %row
            tk.Label(self.frame, text=t).grid(row=row, column=1)

    def onFrameConfigure(self, event):
        '''Reset the scroll region to encompass the inner frame'''
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
    root=tk.Tk()
    Example(root)
    root.mainloop()

Above is my code, a large part of the code comes from this post . And I am concerned when I repeatedly update the label text by using self.l["text"]+=1, there would be rare cases (about 70 instances out of 10000 updates) that it takes around 0.11 sec to update the label text, while the remaining iterations act a lot faster.

I wonder a) why would there be cases where updating become considerably slower? especially when it seems kind of constant to have about 70 slow cases in every iteration of 10000, I wonder if there is any reason for that "constant" time drift. and b) how to avoid those slow instances when running a large iteration loop that requires to update the label text quite often?

I am still uncertain about the reason for the overhead and how to resolve it, but here's a partial way around to reduce the impact.

So we know that there would be about 70 slow cases out of 10000 consecutive runs, I found out that this result is actually proportional to the amount of runs executed. Simply, around every 140 times of execution of tkLabelObject["text"]= "value reassignment" would emerge one slow execution such that it takes 0.01 sec to reassign the value and present on GUI (consider the fact that other 139 executions' time elapse couldn't be catched within 1xe-07 timeframe, that 0.01 sec execution is significantly slow).

As a result, to reduce such impact is to call a short break after about every 130 executions. so doing the following would be able to avoid "slow cases" in updating tkLabel text 10000 times (well, the example code only update 9100 times, but we just need to change the range value in the first for loop to adjust)

import time

for x in range(70):

    time.sleep(0.0000000001) 

    for x in range(130):

        tkLabelObj["text"]= "value reassignment"

But then, this is by no means the best practice. As stated upfront, I consider this to just be a way around until more elegant solutions emerge.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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