1

I am quite new in python and made a Tkinter application that will execute all python files existing in the directory when pressed the start button. My GUI also has progressbar to see the current progress.

so here is my code

import os
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox

directory = dir_path = os.path.dirname(os.path.realpath(__file__))

files = os.listdir(directory)


root = Tk()
root.geometry('200x200')
root.maxsize(200,200)
root.minsize(200,200)
root.title('PYTOEXE')

v = 0
def begin():
    global v
    for x in files:
        os.system('pyinstaller '+x)
        v=v+1
        p['value']=v


p = Progressbar(root,length=200,max=len(files))

b = Button(root,text="Start",command=lambda: begin())



p.place(x=0,y=0)
b.place(x=62,y=30)

root.mainloop()

but my problem is, Whenever i press start button, The GUI freezes and codes start getting compiled and when completed, the GUI unfreezes and the Progressbar fills itself full at once...

So i want the GUI not to freeze while processing and show correct progress on the Progressbar.

Example code and Explanation will be better for me.

Thanks for your valuable time...

2 Answers 2

1

This worked.No need to use .after() to check the thread is finished.

import os
from tkinter import *
from tkinter.ttk import *
import threading

def use_pyinstaller(): # this function is to execute pyinstaller command and add value to progressbar.
    v = 0
    for x in files:
        os.system('pyinstaller '+x)
        v+=1
        p['value'] = v

def begin():
    threading.Thread(target=use_pyinstaller).start() # create a non-block thread to start the function.

directory = dir_path = os.path.dirname(os.path.realpath(__file__))
files = os.listdir(directory)
root = Tk()
root.geometry('200x200')
root.maxsize(200,200)
root.minsize(200,200)
root.title('PYTOEXE')

p = Progressbar(root,length=200,max=len(files))
b = Button(root,text="Start",command=begin)

p.place(x=0,y=0)
b.place(x=62,y=30)

root.mainloop()
Sign up to request clarification or add additional context in comments.

Comments

0

First off, the command argument for the button can just be: command=begin.

GUI toolkits like tkinter are event-driven. They depend on a smooth flow of keyboard and mouse events to work properly. Callbacks (like the command from a button) are called from witin the event loop (root.mainloop). So a callback should only take a short time (say 50 ms) as to not freeze the GUI. You should therefore never run a long-running loop in a callback. You have to program in a different style.

The above link takes you to an article on my website where I compare a simple command-line program with an equivalent GUI program. While that program doesn't use external processes, it illustrates the principle.

The proper way to do this in a GUI, is to start a multiprocessing.Process from the button callback. Then use the root.after method to periodically run a callback that checks if the Process is finished, and then start a new process.

1 Comment

Can u pls put an example code , it's quite hard for me to understand multiprocessing cuz i am new

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.