相关文章推荐
绅士的茴香  ·  安装cplex到python_mob64ca ...·  1 周前    · 
个性的饼干  ·  实用的 Python 之 ...·  4 天前    · 
大气的课本  ·  Flink CDC中flink sql ...·  7 月前    · 
面冷心慈的松球  ·  ResourceHandlerRegistr ...·  10 月前    · 
逃课的日光灯  ·  java - WARN ...·  1 年前    · 
眉毛粗的滑板  ·  excel ...·  1 年前    · 
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.