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.
–
–
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
–
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.