添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I've been developing a tkinter application for downloading a file from the internet and showing the progress of it on a progress bar (Progressbar).

Since the download process was different from the GUI, (and since tkinter runs the GUI the main thread on an infinite loop), I figured to make a different thread for the download process to carry on, and it would update the progress bar in the background

I would then go on to wait for the background process to end, and call the root.destroy() method to end the application, but the application doesn't close, on closing the application manually - it would return the following error

_tkinter.TclError: can't invoke "destroy" command: application has been destroyed

Here is the code for the

class download:
    #Initializing the root
    def __init__(self):
        self.root = Tk()
    #creating the progress bar and packing it to the root
    def create_progress_bar(self):
        self.progress_bar = Progressbar(self.root, orient = HORIZONTAL, length = 200, mode = 'determinate')
        self.progress_bar.pack(pady=10)
    #function to start the mainloop
    def start_application(self):    
        self.root.mainloop()
    #updating the progress bar from the background thread
    def update_progress(self, count, blocksize, totalsize):
        update = int(count * blocksize * 100 / totalsize)
        self.progress_bar['value'] = update
        self.root.update_idletasks()
    #downloading the file from the background thread
    def download_file(self, download_url):
        #using the reporthook to get information about download progress
        urllib.request.urlretrieve(download_url, 'a.jpg', reporthook=self.update_progress)
    #closing the root function
    def close(self):
        self.root.destroy()        
    #handling the download
    def handle_download(self, download_url):
        #creating a different thread
        self.process = Thread(target=self.download_file, args=(download_url,))
        #creating the progress bar
        self.create_progress_bar()
        #starting the background thread
        self.process.start()
        #starting the GUI
        self.start_application()
        #waiting for the background thread to end
        self.process.join()
        #closing the application
        self.close()
ob = download()
ob.handle_download('link')

For what it's worth, I did try to make things happen on the same thread, but the application could not respond to the updates. Any insight on the matter would be extremely welcome.

you need to provide a minimal reproducible example (also per PEP 8 class names should be in CapitalCase) and explain the issue a bit thoroughly – Matiiss Oct 31, 2021 at 17:14 @Armali oh thank you, I couldn't ascertain that my program didn't reach the destroy method. Thank you for solving my issue as well! – SaikumarRajan Nov 1, 2021 at 6:33

Since your program does self.root.destroy() only after self.root.mainloop() has returned, it does not reach the point of destruction unless you're closing the application manually, and then it's pointless to call .destroy().

You could check from time to time whether the download thread is running, and destroy the window when not.

    def watch(self):
        if self.process.is_alive(): self.root.after(500, self.watch)
        else: self.close()
    #handling the download
    def handle_download(self, download_url):
        #starting the background thread
        self.process.start()
        self.watch()
        #closing the application
        #self.close() is too late here
                Thank you so much!! Watching the process for its completion worked. Thank you once again!
– SaikumarRajan
                Nov 1, 2021 at 5:45
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.