-1

I am very new to programming and im trying to make a very simple GUI. I have a problem with the button freezing until it completes the command. I know one can solve it with Threads, but im not sure how. Here is my code now:

#GUI

from tkinter import * 
import time
import threading

window = Tk()
window.title("GTIM" )
window.geometry('360x200')

def clear():
    lbl1.destroy()
    lbl2.destroy()
    btn.destroy()
def prog_bar():
    progress.grid()
    for i in range(300):
        progress['value'] = i
        time.sleep(0.01)

progress = Progressbar(window, orient = HORIZONTAL, length = 300, mode = 'determinate')
progress.grid(column=2, row=7)
progress.grid_remove()

lbl1 = Label(window, text="ГТИМ-2020", font=("Times New Roman", 15))
lbl2 = Label(window, text="Генератор на Теми за Играта Асоциации" , font=("Arial Bold", 10))
btn = Button(window, text="Генерирай!", command = lambda: [clear(), prog_bar()])

lbl1.grid(column = 2, row = 0)
lbl2.grid(column = 2, row = 1)
btn.grid(column=2, row=5)

col_count, row_count = window.grid_size()
for col in xrange(col_count):
   window.grid_columnconfigure(col, minsize=20)
for row in xrange(row_count):
    window.grid_rowconfigure(row, minsize=20)

window.mainloop()

Thanks for the help! Ignore the bulgarian please :D

Kalinka
  • 1
  • 2
  • Hi Kalinka, welcome to both worlds of programming & stackoverflow :) I don't think it is a thread issue, giving a closer look to your code, you are deleting a button, in a function call that is in the command of that button, and after that you execute another function.. how come, the button is deleted by that first function clear(), that in its return couldn't find its caller, the button, can you get my point? – Hasnaa Ibraheem Apr 14 '20 at 13:37
  • @HasnaaIbraheem If i change it to x.grid_remove() it does not change the outcome. After you click the button, it freezes in down position and the whole gui freezes, until it has finished with the porg_bar() command. And after it has finished it unfreezes and does the clear() command. The Idea is that after you press the button everything disappeares the progress bar will apear and start "progressing" – Kalinka Apr 14 '20 at 13:48
  • Ok @Kalinka, what about checking the first code snippet in this link, it talks about some basic thread use that would solve your issue: https://www.python-course.eu/threads.php – Hasnaa Ibraheem Apr 14 '20 at 14:03
  • @HasnaaIbraheem This problem could be solved by thread. – jizhihaoSAMA Apr 14 '20 at 14:26

1 Answers1

0

Two way,use thread:

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

window = Tk()
window.title("GTIM" )
window.geometry('360x200')

def clear():
    lbl1.destroy()
    lbl2.destroy()
    btn.destroy()

def create_thread(): # start a thread
    threading.Thread(target=prog_bar).start() # execute the function.

def prog_bar():
    progress.grid()
    for i in range(300):
        progress['value'] = i
        time.sleep(0.01)

progress = Progressbar(window, orient = HORIZONTAL, length = 300, mode = 'determinate')
progress.grid(column=2, row=7)
progress.grid_remove()

lbl1 = Label(window, text="ГТИМ-2020", font=("Times New Roman", 15))
lbl2 = Label(window, text="Генератор на Теми за Играта Асоциации" , font=("Arial Bold", 10))
btn = Button(window, text="Генерирай!", command = lambda: [clear(), create_thread()])

lbl1.grid(column = 2, row = 0)
lbl2.grid(column = 2, row = 1)
btn.grid(column=2, row=5)

col_count, row_count = window.grid_size()
for col in range(col_count):
   window.grid_columnconfigure(col, minsize=20)
for row in range(row_count):
    window.grid_rowconfigure(row, minsize=20)

window.mainloop()

More safe way is to use .after():

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

window = Tk()
window.title("GTIM" )
window.geometry('360x200')

def clear():
    lbl1.destroy()
    lbl2.destroy()
    btn.destroy()
    window.after(100,prog_bar,0)

def prog_bar(value):
    progress.grid()
    if progress['value']==100: 
        return # stop when value is 100.
    progress['value'] += 10 # a value
    window.after(100, prog_bar,value) # call it each 0.1s

progress = Progressbar(window, orient = HORIZONTAL, length = 300, mode = 'determinate')
progress.grid(column=2, row=7)
progress.grid_remove()

lbl1 = Label(window, text="ГТИМ-2020", font=("Times New Roman", 15))
lbl2 = Label(window, text="Генератор на Теми за Играта Асоциации" , font=("Arial Bold", 10))
btn = Button(window, text="Генерирай!", command = clear)

lbl1.grid(column = 2, row = 0)
lbl2.grid(column = 2, row = 1)
btn.grid(column=2, row=5)

col_count, row_count = window.grid_size()
for col in range(col_count):
   window.grid_columnconfigure(col, minsize=20)
for row in range(row_count):
    window.grid_rowconfigure(row, minsize=20)

window.mainloop()
jizhihaoSAMA
  • 12,336
  • 9
  • 27
  • 49
  • This example violates [All Tcl commands need to originate from the same thread](https://stackoverflow.com/a/26703844/7414759) – stovfl Apr 14 '20 at 15:20
  • @stovfl So I suggest the safe way.`.after()`,but in OP's question,it is a global variable.Ok,could you edit my answer and use a extra thread? – jizhihaoSAMA Apr 14 '20 at 15:26
  • ***could you edit my answer and use a extra thread?***: The OP didn't provide enough information to do so. Also, i can't see if a `.after(...` solution is possible at all. – stovfl Apr 14 '20 at 15:39
  • @stovfl If you run OP's code,you will find his problem.Just because when he press the button.His app will be freezing.So if don't use `thread`,`.after()` could solve freezing. – jizhihaoSAMA Apr 14 '20 at 15:44
  • Your suggestion, **use `thread`, `.after()`**, is ok. But i doubt there is more than a simple `for ...` loop to handle ... – stovfl Apr 14 '20 at 15:51