Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create downloading progress bar in ttk?

I want to show a progress bar while downloading a file from the web using the urllib.urlretrive method.

How do I use the ttk.Progressbar to do this task?

Here is what I have done so far:

from tkinter import ttk from tkinter import *  root = Tk()  pb = ttk.Progressbar(root, orient="horizontal", length=200, mode="determinate") pb.pack() pb.start()  root.mainloop() 

But it just keeps looping.

like image 207
Hanix Avatar asked Sep 05 '11 16:09

Hanix


People also ask

Which function is used to create a ProgressBar in tkinter?

We will create a full-width progress bar by using ProgressBar(win, options) method. It can be configured through a button that enables and disables it.

What is TTK tkinter?

ttk is a module that is used to style the tkinter widgets. Just like CSS is used to style an HTML element, we use tkinter. ttk to style tkinter widgets. Here are the major differences between tkinter widget and tkinter.ttk − Tkinter widgets are used to add Buttons, Labels, Text, ScrollBar, etc., however, tkinter.


1 Answers

For determinate mode you do not want to call start. Instead, simply configure the value of the widget or call the step method.

If you know in advance how many bytes you are going to download (and I assume you do since you're using determinate mode), the simplest thing to do is set the maxvalue option to the number you are going to read. Then, each time you read a chunk you configure the value to be the total number of bytes read. The progress bar will then figure out the percentage.

Here's a simulation to give you a rough idea:

import tkinter as tk from tkinter import ttk   class SampleApp(tk.Tk):      def __init__(self, *args, **kwargs):         tk.Tk.__init__(self, *args, **kwargs)         self.button = ttk.Button(text="start", command=self.start)         self.button.pack()         self.progress = ttk.Progressbar(self, orient="horizontal",                                         length=200, mode="determinate")         self.progress.pack()          self.bytes = 0         self.maxbytes = 0      def start(self):         self.progress["value"] = 0         self.maxbytes = 50000         self.progress["maximum"] = 50000         self.read_bytes()      def read_bytes(self):         '''simulate reading 500 bytes; update progress bar'''         self.bytes += 500         self.progress["value"] = self.bytes         if self.bytes < self.maxbytes:             # read more bytes after 100 ms             self.after(100, self.read_bytes)  app = SampleApp() app.mainloop() 

For this to work you're going to need to make sure you don't block the GUI thread. That means either you read in chunks (like in the example) or do the reading in a separate thread. If you use threads you will not be able to directly call the progressbar methods because tkinter is single threaded.

You might find the progressbar example on tkdocs.com to be useful.

like image 196
Bryan Oakley Avatar answered Sep 23 '22 07:09

Bryan Oakley