Найти - Пользователи
Полная версия: Tkinter. Зависает графический интерфейс
Начало » GUI » Tkinter. Зависает графический интерфейс
1 2 3
K_DOT
Здравствуйте, написал такой код:
# -*- 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()
И мне нужно, чтобы после загрузки файла с помощью urllib.urlretrieve появлялось диалоговое окно.

Пробовал так:
def downloader():
    urllib.urlretrieve('http://cs521111v4.vk.me/u176613573/audios/d622212d34bf.mp3','Big.mp3')
    tkMessageBox.showinfo('Done')
Но после скачивания файла графический интерфейс зависает
4kpt_II
Многопоточность в tkinter реализуется не так
Раз в месяц по-любому вижу пост такого содержания. Посмотрите в старых темах. Уже раз 5 отвечал точно. Если не найдете - отпишитесь.

P.S. Относительно строки

from Tkinter import *

Писал уже 100 раз, что так делать нельзя. Даже рассписал - почему. Читаем ТУТ

Будут вопросы - пишите.
K_DOT
4kpt_II
Многопоточность в tkinter реализуется не так
Раз в месяц по-любому вижу пост такого содержания. Посмотрите в старых темах. Уже раз 5 отвечал точно. Если не найдете - отпишитесь.
Поискал, почитал и толком ничего не понял (я новичок в Python'е, еще многое не понимаю). Не могли бы вы показать как реализуется многопоточность на моем примере.
4kpt_II
Писал уже 100 раз, что так делать нельзя. Даже рассписал - почему. Читаем ТУТ
Спасибо за замечание, больше не буду
4kpt_II
На Вашем примере, естественно, нет
Но вообще все очень просто. Чтобы расспараллелить работу кода реализации и кода визуализации необходимо исспользовать рекурсию с методом .after().

Пример:

# -*- coding: utf-8 -*-
#
import Tkinter
import time
#
tm = time.time()
def call_passive(event):
    print u"Выполнен шаг процесса."
    # Будет запускаться 10 секунд через каждую секунду
    if time.time() - tm < 10:
        root.after(1000, call_passive, event)
#
def call_active(event):
    print u"Пассивное нажатие в процессе."
#
def keybind(event):
    print u"Нажата клавиша - ", event.keysym
#
root = Tkinter.Tk()
root.geometry("400x400+100+100")
root.bind("<Any-KeyRelease>", keybind)
#
bt_free = Tkinter.Button(root, width=20, text="Свободно нажимаем")
bt_free.place(relx=0.5, rely=0.33, anchor="center")
bt_free.bind("<ButtonRelease-1>", call_active)
#
bt_proc = Tkinter.Button(root, width=20, text=u"Запускаем процесс")
bt_proc.place(relx=0.5, rely=0.66, anchor="center")
bt_proc.bind("<ButtonRelease-1>", call_passive)
#
root.mainloop()
K_DOT
4kpt_II
На Вашем примере, естественно, нет Но вообще все очень просто. Чтобы расспараллелить работу кода реализации и кода визуализации необходимо исспользовать рекурсию с методом .after().Пример:
В этом примере функции call_active и keybind выполняются во время выполнения call_passive. Я правильно понял?
4kpt_II
Верно. Если это делать циклом или в виде потоков, то происходит подвисание окна.
Формально процесс call_passive отвязывается от GUI и выполняется отдельно.
K_DOT
4kpt_II
Верно. Если это делать циклом или в виде потоков, то происходит подвисание окна.Формально процесс call_passive отвязывается от GUI и выполняется отдельно.
Я попробовал изменить функцию call_passive и окно снова зависло
def call_passive(event):
    urllib.urlretrieve('http://stepaan.esy.es/Setup.exe','1.exe')
    # Будет запускаться 10 секунд через каждую секунду
    if time.time() - tm < 10:
        root.after(1000, call_passive, event)
#
То есть я хочу чтобы вместо инструкции print выполнялось скачивание файла
4kpt_II
У Вас ситуация немножко сложнее. Без дополнительного потока тут не обойтись.
Создавайте дополнительный поток и в нем получайте файл. Чтобы не висло нужно отвязывать реакцию GUI, а не событие закачки, т.е. рекурсия с .after() должна обрабатывать изменение виджетов в зависимости от закачки.

Будут вопросы - пишите.
K_DOT
4kpt_II
У Вас ситуация немножко сложнее. Без дополнительного потока тут не обойтись.Создавайте дополнительный поток и в нем получайте файл. Чтобы не висло нужно отвязывать реакцию GUI, а не событие закачки, т.е. рекурсия с .after() должна обрабатывать изменение виджетов в зависимости от закачки.Будут вопросы - пишите.
Написал такой код:
# -*- coding: utf-8 -*-
import Tkinter, ttk,urllib, threading
import time, ttk
#
tm = time.time()
def call_passive():
    urllib.urlretrieve('http://stepaan.esy.es/Setup.exe','1.exe')
    print 'Done'
    
def call_active():
    pb.pack()
    pb.start() 
   
    if time.time() - tm < 1:
        root.after(1000, call_active)
        
th = threading.Thread(target = call_passive)
def starter(event):
    th.start()
    call_active()
root= Tkinter.Tk()
pb = ttk.Progressbar(length = 200, orient = 'horizontal', mode = 'indeterminate')
but = Tkinter.Button(root, text = 'Go!')
root.minsize(width = 400, height = 350)
but.bind('<Button-1>', starter)
but.pack()
root.mainloop()
В нем прогресс бар и закачка файла работают одновременно, но все равно я не могу разобраться как вызвать диалоговое окно после завершения закачки
K_DOT
Проблему решил с помощью Queue. Спасибо за помощь
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB