Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » Tkinter. Зависает графический интерфейс [RSS Feed]

#1 Янв. 13, 2014 14:01:59

K_DOT
Зарегистрирован: 2014-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

Здравствуйте, написал такой код:

# -*- 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')
Но после скачивания файла графический интерфейс зависает

Отредактировано K_DOT (Янв. 13, 2014 14:03:39)

Офлайн

#2 Янв. 13, 2014 14:43:57

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

Многопоточность в tkinter реализуется не так
Раз в месяц по-любому вижу пост такого содержания. Посмотрите в старых темах. Уже раз 5 отвечал точно. Если не найдете - отпишитесь.

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

from Tkinter import *

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

Будут вопросы - пишите.

Отредактировано 4kpt_II (Янв. 13, 2014 14:46:23)

Офлайн

#3 Янв. 13, 2014 15:57:37

K_DOT
Зарегистрирован: 2014-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

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

Офлайн

#4 Янв. 13, 2014 16:15:34

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

На Вашем примере, естественно, нет
Но вообще все очень просто. Чтобы расспараллелить работу кода реализации и кода визуализации необходимо исспользовать рекурсию с методом .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()

Офлайн

#5 Янв. 13, 2014 17:35:07

K_DOT
Зарегистрирован: 2014-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

4kpt_II
На Вашем примере, естественно, нет Но вообще все очень просто. Чтобы расспараллелить работу кода реализации и кода визуализации необходимо исспользовать рекурсию с методом .after().Пример:
В этом примере функции call_active и keybind выполняются во время выполнения call_passive. Я правильно понял?

Офлайн

#6 Янв. 13, 2014 17:48:45

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

Верно. Если это делать циклом или в виде потоков, то происходит подвисание окна.
Формально процесс call_passive отвязывается от GUI и выполняется отдельно.

Офлайн

#7 Янв. 13, 2014 17:54:47

K_DOT
Зарегистрирован: 2014-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

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 выполнялось скачивание файла

Офлайн

#8 Янв. 13, 2014 20:16:25

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

У Вас ситуация немножко сложнее. Без дополнительного потока тут не обойтись.
Создавайте дополнительный поток и в нем получайте файл. Чтобы не висло нужно отвязывать реакцию GUI, а не событие закачки, т.е. рекурсия с .after() должна обрабатывать изменение виджетов в зависимости от закачки.

Будут вопросы - пишите.

Офлайн

#9 Янв. 14, 2014 11:17:55

K_DOT
Зарегистрирован: 2014-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

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 (Янв. 14, 2014 12:02:47)

Офлайн

#10 Янв. 14, 2014 13:12:46

K_DOT
Зарегистрирован: 2014-01-13
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter. Зависает графический интерфейс

Проблему решил с помощью Queue. Спасибо за помощь

Офлайн

  • Начало
  • » GUI
  • » Tkinter. Зависает графический интерфейс[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version