移动Tkinter窗口时程序停止
你好!
我写了一个音乐下载程序,运行得很好,它会告诉你下载进度百分比。但是如果我稍微移动一下窗口,下载就会停止。
我又写了一个小脚本,可以下载网上指定的mp3文件,移动窗口的时候它不会停止,随便怎么动都没问题。
我之所以不分享我的代码,是因为它实在太长了,大约有1500行。不过我可以分享这个小脚本,用来下载一个文件。
有没有人知道为什么我的程序会停止工作呢?
这个小脚本是:
from Tkinter import *
from urllib2 import *
admin = Tk()
Admin = Tk()
listbox = Listbox(admin, bg="PURPLE")
listbox.pack()
def __init__(self, master):
def replay():
Admin.destroy()
os.system('WhaleWire.exe')
frame = Frame(master)
frame.pack()
image1 = PhotoImage(file="whalewire.gif")
w = image1.width()
h = image1.height()
master.geometry("%dx%d+0+0" % (w, h))
# tk.Frame has no image argument
panel1 = Label(master, image=image1)
panel1.pack(side='top', fill='both', expand='yes')
panel1.image = image1
self.e = Entry(frame)
self.e.grid(row=0, column=0)
b = Button(frame, text='Search', command=self.whale)
b.grid(row=0, column=1)
def library():
path = 'C:\WhaleWire\Downloaded'
aw=[]
for infile in glob.glob( os.path.join(path,'*.mp3') ):
libr = infile.split('Downloaded',1)
aw.append('\n')
aw.append(infile)
la = Label(Admin,width=100,height=50, text=aw).grid(row=0,column=7)
b2s = Button(Admin,text='Search', command=replay).grid(row=0,column=8)
b11 = Button(frame, text='Library', command=library)
b11.grid(row=0, column=3)
def fores():
chunks = 10000
dat = ''
song = '3 rounds and a sound'
url = 'http://bonton.sweetdarkness.net/music/Blind%20Pilot%20--%203%20Rounds%20and%20A%20Sound.mp3'
down = urlopen(url)
downso = 0
tota = down.info().getheader('Content-Length').strip()
tota = int(tota)
while 1:
a = down.read(chunks)
downso += len(a)
if not a:
break
dat += a
percent = float(downso) / tota
percent = round(percent*100, 1)
listbox.insert(END, percent)
listbox.update()
listbox.delete(0, END)
listbox.insert(END, percent)
listbox.update()
button = Button(Admin, text='Download', command=fores)
button.pack()
button = Button(Admin, text='Download', command=fores)
button.pack()
mainloop()
1 个回答
2
很可能你遇到的问题是因为你在调用 update
。除非你非常清楚这样做的后果,否则最好不要这样做。调用 update
会让程序进入一个新的事件循环。简单来说,你就会在一个无限循环里再套一个无限循环。
试试把你的 update
改成 update_idletasks
,看看这样能不能解决你的问题。这个 update
的变体只处理一些“空闲”事件,比如屏幕重绘,出问题的可能性要小得多。
另外,你完全不需要写“update; insert; delete; update”这样的代码。这不会有什么明显的效果。在删除操作后,只需要调用一次 update_idletasks
就足够了。
最后,你可以通过重新安排你的代码来完全避免使用 update_idletasks
。写一个函数来读取一小块数据并更新进度条。如果还没有到达文件末尾(EOF),就用 after
在几毫秒后再次调用这个函数。当到达文件末尾时,它就会停止调用自己。这样做的好处是你不需要自己创建一个可能无限的循环,事件循环每次迭代时都会被保证进入一次。一旦检测到文件末尾,你就可以再用 after
调用一个函数来进行最后的处理。