Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tkinter gui with progress bar

Tags:

python

tkinter

I have a simple Tk GUI and a long process in a function attached to a button. I want a progress bar when I click on the button, just like it starts a long process.

How can I do that? This is my current code:

from tkinter import Button, Tk, HORIZONTAL

from tkinter.ttk import Progressbar
import time


class MonApp(Tk):
    def __init__(self):
        super().__init__()

        bt1 = Button(self, text='Traitement', command=self.traitement)
        bt1.grid()
        self.progress = Progressbar(self, orient=HORIZONTAL, length=100, mode='indeterminate')
        self.progress.grid()
        self.progress.grid_forget()

    def traitement(self):
        self.progress.grid()
        self.progress.start()
        time.sleep(15) 
        ## Just like you have many, many code lines...

        self.progress.stop()


if __name__ == '__main__':
    app = MonApp()
    app.mainloop()

How can I put a progress bar in that application?

like image 920
j666 Avatar asked Nov 17 '15 22:11

j666


People also ask

How to use progress bar in Tkinter Python?

Use the ttk. Progressbar(container, orient, length, mode) to create a progressbar. Use the indeterminate mode when the program cannot accurately know the relative progress to display. Use the determinate mode if you know how to measure the progress accurately.

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 −

What is Treeview in tkinter?

Introduction to the Tkinter Treeview widgetA Treeview widget allows you to display data in both tabular and hierarchical structures. To create a Treeview widget, you use the ttk.Treeview class: tree = ttk.Treeview(container, **options) A Treeview widget holds a list of items. Each item has one or more columns.


2 Answers

You can find ttk.Progressbar at tkdocs

import time
from tkinter import *
from tkinter.ttk import *

tk = Tk()
progress = Progressbar(tk, orient=HORIZONTAL, length=100, mode='determinate')


def bar():
    progress['value'] = 20
    tk.update_idletasks()
    time.sleep(1)
    progress['value'] = 50
    tk.update_idletasks()
    time.sleep(1)
    progress['value'] = 80
    tk.update_idletasks()
    time.sleep(1)
    progress['value'] = 100

progress.pack()
Button(tk, text='foo', command=bar).pack()
mainloop()

It's better to use threading and run your code in another thread.

Like this:

import threading
import time
from tkinter import Button, Tk, HORIZONTAL
from tkinter.ttk import Progressbar

class MonApp(Tk):
    def __init__(self):
        super().__init__()

        self.btn = Button(self, text='Traitement', command=self.traitement)
        self.btn.grid(row=0, column=0)
        self.progress = Progressbar(self, orient=HORIZONTAL, length=100, mode='indeterminate')

    def traitement(self):
        def real_traitement():
            self.progress.grid(row=1,column=0)
            self.progress.start()
            time.sleep(5)
            self.progress.stop()
            self.progress.grid_forget()

            self.btn['state']='normal'

        self.btn['state']='disabled'
        threading.Thread(target=real_traitement).start()


if __name__ == '__main__':
    app = MonApp()
    app.mainloop()
like image 122
xmcp Avatar answered Oct 13 '22 05:10

xmcp


For all the GUI elements to modify themselves (in your case, for the progress bar to move) the execution must hit app.mainloop().

In your case, def traitement(self): starts and then stops the progressbar without hitting the mainloop, so it fails to visibly reflect the intended progressbar movement on the GUI. The catch here is, when the execution hits mainloop, progressbar is configured to 'stop' state.

Hence, it is a good idea to execute time consuming activities on a different Thread as shown by @xmcp

However, if you DO NOT want to use threading, you can use the after method to achieve what you want:

def stop_progressbar(self):
    self.progress.stop()

def traitement(self):
    self.progress.grid()
    self.progress.start()
    self.after(15000, self.stop_progressbar) 
    ## Call Just like you have many, many code lines...

The above code used self.after() method which will execute the stop_progressbar method to stop after 15 seconds, instead of time.sleep() which blocks the mainthread.

like image 40
MightyInSpirit Avatar answered Oct 13 '22 04:10

MightyInSpirit