Неблокирующая заправка и кнопка «остановить резьбу» в Tkinter - PullRequest
0 голосов
/ 09 февраля 2020

У меня есть программа Tkinter с текстовой областью, в которую можно вставить список URL-адресов YouTube, и рядом с ней кнопка «Загрузить», которая загружает видео по URL-адресам в папку на моем компьютере. Я использую модуль pafy для загрузки видео.

Я настроил это так, что при нажатии кнопки запускается поток, который запускает функцию для загрузки видео. Я подумал с поточностью, что это оставит программу без изменений, но через несколько секунд после того, как я нажму кнопку, хотя видео загружается нормально, программа блокируется, в верхней части программы появляется сообщение «Не отвечает» и остается таковым. вплоть до прекращения работы функции, успешно завершив загрузку. Другими словами, программа блокируется запущенной функцией / потоком и имеет эту маленькую штуку с песочными часами, которая отключает любые другие щелчки или интерактивность с программой до завершения загрузки.

У меня также есть кнопка рядом с кнопкой «Загрузить». Кнопка с надписью «Стоп», чтобы остановить загрузку при каждом нажатии. Очевидно, что поскольку вся программа заблокирована, даже с потоками, во время загрузки видео нельзя нажать кнопку «Стоп».

Может кто-нибудь указать, как заставить поток работать без блокировки программы и как запустить кнопку «Стоп» в таком случае? Вот код:

import pafy
from threading import Thread

def downloadvideos():
    textdata = text1.get('1.0', 'end-1c').splitlines()
    downloadlist=[]
    downloadlist1 = []
    downloaddict = {}
    for t in textdata:
        print t
        downloadlist.append(t)
        print downloadlist
        try:
            url = t
            video = pafy.new(url)
            best = video.getbest()
            title = video.title
            best.download(filepath=foldername)
            downloaddict[title] = url
        except Exception:
            sys.exc_clear()

def but1thread():
    global thethread
    thethread = Thread(target=downloadvideos, name='firstthread')
    thethread.daemon = True
    thethread.start()
    thethread.join()

def but1stop():
    thethread.running = False


button1 = Button(frame1, text="Download", activebackground="green", command=but1thread)
button1.grid(row=1, column=0, sticky=W, padx=(10, 0), pady=(20, 0))

button2 = Button(frame1, text="Stop", background="red", command=but1stop)
button2.grid(row=1, column=1)

1 Ответ

0 голосов
/ 09 февраля 2020

Вызывающий thethread.join() заблокирует tkinter mainl oop, поэтому он не должен вызываться.

Чтобы остановить загрузку, вы можете использовать опцию callback best.download(...). Внутри функции обратного вызова проверьте, нажата ли кнопка Stop. Если да, то вызовите исключение, чтобы остановить загрузку:

def on_downloading(*args):
    if not thethread.running:
      print '\ncancelling ...'
      raise Exception('download cancelled')

def downloadvideos():
    textdata = text1.get('1.0', 'end-1c').splitlines()
    downloadlist=[]
    downloadlist1 = []
    downloaddict = {}
    thethread.running = True
    for t in textdata:
        if not thethread.running:
            break
        print t
        downloadlist.append(t)
        print downloadlist
        try:
            url = t
            video = pafy.new(url)
            best = video.getbest()
            title = video.title
            best.download(filepath=foldername, callback=on_downloading)
            downloaddict[title] = url
        except Exception as e:
            print e
            sys.exc_clear()
    print('download completed')

def but1thread():
    global thethread
    thethread = Thread(target=downloadvideos, name='firstthread')
    thethread.daemon = True
    thethread.start()
    #thethread.join()  # join() will block the tkinter mainloop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...