首页 > 解决方案 > 下载文件时 Tkinter UI 被阻止

问题描述

我在 python 中编写了一些代码来下载文件,但是当代码下载文件时,我无法更新 UI。下面是代码

import tkinter as tk
from tkinter import ttk, Button, Label, Frame
from tkinter.scrolledtext import ScrolledText
from datetime import timedelta,datetime
import sys
import requests
import urllib
from socket import timeout
from threading import Thread

    
class App():
    # declare the window
    urls = []
    def __init__(self):
        
        self.window = tk.Tk()
        
    
        # set window title
        self.window.title("Downloader")
        # set window width and height
        self.window.configure(width=500, height=300)
        self.window.minsize(500, 300)
        # set window background color
        self.window.configure(bg='lightgray')
        self.window.configure(background="white")
        
        self.frame = Frame(self.window)
        url_label = Label(self.frame, text = "Enter URL")
        url_label.pack_configure(side="left", anchor="center", fill="x", expand=0)
        
        self.urlEntry = tk.Entry(self.frame)
        self.urlEntry.pack_configure(side="left", anchor="center", fill="x", expand=1)
        
        
        self.frame.pack_configure(side="top", fill="x",anchor="center", expand=1)
        url_label.pack()
        self.urlEntry.pack()
        self.frame.pack()
          
        
        # Add Button and Label
        download_button = Button(self.window, text = "Start Download",
               command = self.startDownload)
        
        download_button.pack(side="top", anchor="nw", fill="x", expand=1)
        
          
        self.date = Label(self.window, text = "")
        self.date.pack(side="top", anchor="nw", fill="x", expand=1)
        
        
        self.console = ScrolledText(self.window,relief="solid",wrap = tk.WORD)
        self.console.configure(font='TkFixedFont', background="gray")
        self.console.configure(state="disabled")
        self.console.pack(side="top",padx=10, pady=10, fill="x", expand=1)        
        
        self.console.configure(state="disabled")
        self.window.mainloop()
        
        
    def writeLog(self, text):
        self.console.configure(state="normal")
        self.console.insert(tk.INSERT,text+"\n")
        self.console.configure(state="disabled")
        
        
    def startDownload(self):
        self.url = self.urlEntry.get()
        self.urls.append(self.url)
        threads=list()
        for url in self.urls:
            self.writeLog(datetime.now().strftime("%d/%m/%Y %H:%M:%S :- ")+"Downloading "+url)
            print(url)
#             self.writeLog(url)
            firstpos=url.rfind("/")
            lastpos=len(url)
            filename = url[firstpos+1:lastpos]
            t = Thread(target=self.downloadFile, args=(url, filename,))
            t.start()
            threads.append(t)
            
        for thread in threads:
            thread.join()
    
    
    def downloadFile(self, url, filename):
        isFileExist = self.fileExist(url)
        if isFileExist:
            with open(filename, "wb") as f:
                print("Downloading %s" % filename)
#                 self.writeLog( "Downloading %s" % filename)
                response = requests.get(url, stream=True)
                total_length = response.headers.get('content-length')
                print(total_length)
                  
                if total_length is None: # no content length header
#                     f.write(response.content)
                    print("No File:"+url)
                else:
                    dl = 0
                    total_length = int(total_length)
                    for data in response.iter_content(chunk_size=4096):
                        dl += len(data)
                        f.write(data)
                        done = int(50 * dl / total_length)
                        sys.stdout.write("\r[Downloading %s :%s%s]" % (filename, '=' * done, ' ' * (50-done)) )    
                        sys.stdout.flush()
                        if done == 50 :
                            self.writeLog(datetime.now().strftime("%d/%m/%Y %H:%M:%S :- ")+filename+" Download completed  ")
                f.close()
    
    def fileExist(self, url):
        try:
            response = urllib.request.urlopen(url,timeout=5)
            status_code = response.getcode()
            if status_code == 200:
                return True
            else:
                return False
        except urllib.request.HTTPError:
            return False
        except timeout:
            return False
    
if __name__ == '__main__':
    App()

请告知代码有什么问题

标签: python-3.xtkinterpython-requests

解决方案


推荐阅读