我的python tkinter代码在linux中严重滞后,但在Windows中却严重滞后。它与root.update()和root.config()有关。如何解决此问题,使linux版本与Windows版本一样快?
我已经在Windows上编写了一个运行良好的python程序。我目前正在制作linux版本。进行一些修改后,Linux版本可以正常工作,但有很大的滞后。我插入代码来计时程序的不同部分。对于root.update()
和root.config()
行,从Windows到Linux有很大的不同。
以下几行是导致延迟的行:
root.update()
root.config(menu=menubar)
我在Windows和Linux中多次运行了该程序,并记录了执行代码所花费的时间。
以下是这些行的运行时间的记录:
在Windows中:
root update: 0.47 seconds
root update: 0.2656 seconds
root update: 0.3125 seconds
root update: 0.3594 second
root update: 0.3593 seconds
menubar root config done: 0.0081
menubar root config done: 0.0
在Windows中:进程结束,退出代码为-1
pycharm使用的是Python 3.7
在Linux中:
root update: 2.4416 seconds
root update: 87.3216 seconds
root update: 1.5798 seconds
root update: 148.2783 seconds
root update: 2.2533 seconds
root update: 2.2771 seconds
root update: 2.4898 seconds
root update: 8.022 seconds
root update: 171.6852 seconds
root update: 1.7088 seconds
menubar root config done: 0.0441
menubar root config done: 2.4566
menubar root config done: 1.2589
在linux中:进程以退出代码9
Linux中的pycharm使用的是Python 3.6
这是我能做到的简单代码。 tkinter制作了一个gui,查询mysql数据库,该函数生成菜单栏并将许多小部件放在网格中。
root = Tk()
root.title("KLUSTERBOX")
...
def main_frame(): # call function to make the main screen
# define and put widgets on a grid
...
generate_menubar(Frame) # call function to make menubar
# define the menubar
root.config(menu=menubar)
...
# define and put widgets on a grid
root.update()
我被要求提供MCVE。这是一个示例程序,重复了该问题:
from tkinter import *
import time
import sys
def main_frame():
starttime = time.time()
F = Frame(root)
F.pack(fill=BOTH, side=LEFT)
C1 = Canvas(F)
C1.pack(fill=BOTH, side=BOTTOM)
Button(C1, text="Refresh", width=12, command=lambda: [F.destroy(),main_frame()]).pack(side=LEFT)
Button(C1, text="Quit", width=12, command=root.destroy).pack(side=LEFT)
# link up the canvas and scrollbar
S = Scrollbar(F)
C = Canvas(F, width=1600)
S.pack(side=RIGHT, fill=BOTH)
C.pack(side=LEFT, fill=BOTH, pady=10, padx=10)
S.configure(command=C.yview, orient="vertical")
C.configure(yscrollcommand=S.set)
if sys.platform == "win32":
C.bind_all('<MouseWheel>', lambda event: C.yview_scroll(int(-1 * (event.delta / 120)), "units"))
elif sys.platform == "linux":
C.bind_all('<Button-4>', lambda event: C.yview('scroll',-1,'units'))
C.bind_all('<Button-5>', lambda event: C.yview('scroll',1,'units'))
# create the frame inside the canvas
preF=Frame(C)
C.create_window((0, 0), window=preF, anchor=NW)
Label(preF, text="To refresh - press REFRESH").pack()
Label(preF, text="To quit - press QUIT").pack()
Label(preF, text="Run times are displayed in console").pack()
FF = Frame(C)
C.create_window((0,108), window=FF, anchor=NW)
for i in range(100):
Button(FF, text=i, width=5, bg="yellow", anchor="w").grid(row=i,column=0)
Button(FF, text="hello there", width=24, bg="yellow", anchor="w").grid(row=i,column=1)
Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=2)
Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i,column=3)
Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=4)
Button(FF, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=5)
endtime = time.time()
print("runtime prior to root.update(): ", round(endtime - starttime,4), " seconds")
starttime = time.time()
root.update()
endtime = time.time()
print("root.update() runtime: ", round(endtime-starttime,4)," seconds")
C.config(scrollregion=C.bbox("all"))
mainloop()
root = Tk()
root.geometry("%dx%d+%d+%d" % (625,600,100,50))
main_frame()
我已经为root.update()
和root.config(menu=menubar)
设置了运行时间。 linux中的时间太长,会使该程序无法使用,特别是考虑到该程序的其他部分滞后得多。
答案 0 :(得分:0)
在我的Linux Mint上,它需要0.3秒(Python 3.7、3.6、2.7),而且我不知道为什么它在Linux上运行这么慢。
这里只有一些更改的代码-也许会有所帮助。
我不使用root.update()
,而是使用after()
在主循环启动100毫秒后更改scrollregion
。在mainloop
运行之前,窗口小部件不存在,因此无法计算滚动区域。
我不会使用所有小部件销毁F
,但我只会使用创建表格的按钮来构成框架,而我只会重新创建该框架。
我不再运行main_frame
,所以我不再运行另一个mainloop()
我不得不使用global
来访问带有表的框架,因为command=
无法从函数中获取值并无法赋值给变量。
启动需要0.3秒,刷新需要0.09秒
。
from tkinter import *
import time
import sys
def create_table(C):
table = Frame(C)
C.create_window((0,108), window=table, anchor=NW)
for i in range(100):
Button(table, text=i, width=5, bg="yellow", anchor="w").grid(row=i,column=0)
Button(table, text="hello there" + str(X), width=24, bg="yellow", anchor="w").grid(row=i,column=1)
Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=2)
Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i,column=3)
Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=4)
Button(table, text=" ", width=5, bg="green", anchor="w").grid(row=i, column=5)
return table
def refresh(C):
global table
starttime = time.time()
table.destroy()
table = create_table(C)
endtime = time.time()
print("refresh: ", round(endtime-starttime,4)," seconds")
def main_frame():
global table
starttime = time.time()
F = Frame(root)
F.pack(fill=BOTH, side=LEFT)
C1 = Canvas(F)
C1.pack(fill=BOTH, side=BOTTOM)
Button(C1, text="Refresh", width=12, command=lambda:refresh(C)).pack(side=LEFT)
Button(C1, text="Quit", width=12, command=root.destroy).pack(side=LEFT)
# link up the canvas and scrollbar
S = Scrollbar(F)
C = Canvas(F, width=1600)
S.pack(side=RIGHT, fill=BOTH)
C.pack(side=LEFT, fill=BOTH, pady=10, padx=10)
S.configure(command=C.yview, orient="vertical")
C.configure(yscrollcommand=S.set)
if sys.platform == "win32":
C.bind_all('<MouseWheel>', lambda event: C.yview_scroll(int(-1 * (event.delta / 120)), "units"))
elif sys.platform == "linux":
C.bind_all('<Button-4>', lambda event: C.yview('scroll',-1,'units'))
C.bind_all('<Button-5>', lambda event: C.yview('scroll',1,'units'))
# create the frame inside the canvas
preF=Frame(C)
C.create_window((0, 0), window=preF, anchor=NW)
Label(preF, text="To refresh - press REFRESH").pack()
Label(preF, text="To quit - press QUIT").pack()
Label(preF, text="Run times are displayed in console").pack()
table = create_table(C)
endtime = time.time()
print("runtime: ", round(endtime - starttime,4), " seconds")
# update scrollregion 100ms after mainloop start
root.after(100, lambda:C.config(scrollregion=C.bbox("all")))
mainloop()
root = Tk()
root.geometry("%dx%d+%d+%d" % (625,600,100,50))
main_frame()