更新Tkinter列表框的更好方法

时间:2011-05-10 03:55:47

标签: python tkinter urllib2

您好 所以我首先制作了一个程序来下载音乐,并在列表框中显示已下载的百分比。

有点像这样

    from Tkinter import *
from urllib2 import *
admin = Tk()
Admin = Tk()

listbox = Listbox(admin, bg="PURPLE")
listbox.pack()

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()

我不会告诉你它原来的节目超过了帖子大小的限制。

在我的原始程序中,如果我在下载mp3文件之前移动窗口,它下载的内容少于3%并停止,如果我关闭窗口则会再次开始下载。

有没有人知道为什么会这样,或者是否有替代方法在Tkinter窗口上显示百分比? 请帮忙

和update_idletasks doesent work

2 个答案:

答案 0 :(得分:1)

显示字符串的正确小部件是Label。您可以使用configure方法在运行时更改文本:

self.progress = Label(...)
...
self.progress.configure(text="%s%% completed" % percent)

其次,您要创建两个根窗口 - adminAdmin。奇怪的是,你将列表框放在一个,按钮放在另一个。 Tk的设计不是那样的。第三,你需要调用你的(单个)根窗口的mainloop方法(例如:Admin.mainloop

最后,关于update_idletasks不起作用的评论,请定义“不起作用”。它实际上会更新显示。它不会做的是让你在窗口运行时与窗口进行交互。

我根据上述评论对您的代码进行了更改(仅创建了一个根,使用了Label而不是Listbox,并使用了update_idletasks,程序运行完成,下载这首歌。

调用update的危险是这样的:如果您在下载时点击“下载”按钮怎么办?发生的事情是下次update被调用时,将按下按钮。在为该事件提供服务时,您将进入无限循环。当内部无限循环运行时,外部循环无法运行。您将有效冻结第一次下载。

正确的解决方案涉及(至少)两种技术之一。一,创建一个线程进行下载,并让它定期将信息发送回主循环,以便更新进度条。第二种方法是利用已经存在的无限循环 - 事件循环 - 并通过after将事件放在事件队列中,一次一个地读取块。

互联网上有两种方法的例子。

答案 1 :(得分:0)

我使用ttk.Progressbar,您只需将变量关联到它并更新该特定变量。

http://docs.python.org/library/ttk.html#progressbar

http://www.tkdocs.com/tutorial/morewidgets.html#progressbar