R
R
Ruben Harutyunov2014-01-13 15:33:31
Python
Ruben Harutyunov, 2014-01-13 15:33:31

Python Tkinter. Why does the GUI freeze?

Hello! Help solve the problem, please.
Wrote this code:

# -*- coding: utf-8 -*-
from Tkinter import *
import urllib,  ttk, tkMessageBox
from threading import Thread
def downloader():
    urllib.urlretrieve('http://cs521111v4.vk.me/u176613573/audios/d622212d34bf.mp3','Big K.R.I.T. – Bigger Picture.mp3')  
th=Thread(target=downloader,args=())
def starter(event):
    th.start()
    pb.pack()
    pb.start()   
root= Tk()
pb = ttk.Progressbar(length = 200, orient = 'horizontal', mode = 'indeterminate')
but = Button(root, text = 'Go!')
root.minsize(width = 400, height = 350)
but.bind('<Button-1>', starter)
but.pack()
root.mainloop()

And I need a dialog box to pop up after downloading a file using urllib.urlretrieve.
Tried like this:
def downloader():
    urllib.urlretrieve('http://cs521111v4.vk.me/u176613573/audios/d622212d34bf.mp3','Big.mp3')
    tkMessageBox.showinfo('Done')

But after downloading the file, the GUI freezes. What am I doing wrong?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
mysticmirage, 2014-01-14
@K_DOT

# -*- coding: utf-8 -*-

from Tkinter import *
import urllib, ttk, tkMessageBox
from threading import Thread
from Queue import Queue

queue = Queue()  # создаём очередь

def downloader():
    urllib.urlretrieve('http://cs521111v4.vk.me/u176613573/audios/d622212d34bf.mp3', 'Big K.R.I.T. – Bigger Picture.mp3')
    queue.put(True)  # помещаем в очередь True, после завершения загрузки. В очередь можно помещать любой объект.

th = Thread(target=downloader, args=())

def starter(event):
    th.start()
    pb.pack()
    pb.start()

root = Tk()

# создаём задачу, которая раз в секунду будет проверять очередь
def task():
    try:
        q = queue.get_nowait()  # получить значение из очереди
    except:  # если в очереди ничего нет, то возвращаем False
        q = False
    if q:  # если вернулось True, то сообщаем об окончании
        tkMessageBox.showinfo('Done')
    root.after(1000, task)  # снова перезапускаем задачу после выполнения

root.after(1000, task)  # инициализация задачи

pb = ttk.Progressbar(length=200, orient='horizontal', mode='indeterminate')
but = Button(root, text = 'Go!')
root.minsize(width=400, height=350)
but.bind('<Button-1>', starter)
but.pack()
root.mainloop()

M
mysticmirage, 2014-01-14
@mysticmirage

You cannot call Tkinter methods from threads other than the main thread (where root = Tk()).
There are two options here:
1. Try using mtTkinter.
2. Pass information about the completion of the download from the child thread to the main thread using Queue.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question