Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
809 views
in Technique[技术] by (71.8m points)

python 2.7 - How can I stop my Tkinter GUI from freezing when I click my button?

As someone who is new to programming, I constantly find myself running into errors and issues and, while finding answers and solution, I rarely find out why it is that way. This time, it with Tkinter on Python 2.7. The issue at hand is every time the "submit" button I created is pressed, the GUI freezes. Research has told me that the issue is because there is no callback to allow the program to reach the mainloop. The problem i am facing is the program that runs with the GUI is a never ending automation loop on a timer. I've searched on this site as well, but, like usual, I only get answers where it says things like "Do this because I said it works". As someone who is really interested and trying to get deeper and deeper into the glorious black hole that is programming, an explanation of why it needs to be that way and how you came to that conclusion would be a big help to me. I fully understand that programming is one of those things that is so broad, yet so particular, that explanations become different and sometimes bias, but I find it difficult to learn any other way.

The simplified version of my code I have so far is as follows: (I know simplified code is not preferred on this site, but I don't have the means to transfer the code to any other computer without writing it all down and typing it on here. I know you guys will yell at me for it later. So, for that, I am sorry.)

import os
import time
from datetime import datetime
import shutil
from Tkinter import *

root=Tk()
root.title("Automation")
root.config(bg="black")
root.geometry("500x500")

def submit():
    input=e1.get()
    #the input is a limit set for a variable in the timer that when
    #it hits that limit, it jumps to the 400 lines of code
    def Timer():
        <timer code>
    <400 lines of code that has been tested to work 100%>
    Timer()

b1=Button(root, command=submit)
button.grid(row=0, column =0)
e1=Entry(root, width=50)
e1.grid(row=0, column=1)

mainloop()

Also, as I find it hard to discover and clear information on how to GUI program without it saying "Hey... just do this because I said so", and links to some study/reference materials would be greatly appreciated.

As always, I greatly appreciate all of the help that is provided throughout this site and all of the vastly intelligent individuals that make it the place that it is. Thank you all!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

the reason your Tk GUI freezes is because you have everything running on 1 thread. The mainloop is haulted by the submit function call which must be taking a "long time", so you probably see "Not Responding" appear in your Tk window when you click the button. To fix this, you need spawn a separate thread for submit to run in, so that the mainloop can keep doing it's thing and keep your Tk window from freezing.

this is done using threading. Instead of your button directly calling submit, have the button call a function that starts a new thread which then starts submit. Then create another functions which checks on the status of the submit thread. You can add a status bar too

import os
import time
from datetime import datetime
import shutil
import threading
from Tkinter import *
import ttk

def submit():
    time.sleep(5) # put your stuff here


def start_submit_thread(event):
    global submit_thread
    submit_thread = threading.Thread(target=submit)
    submit_thread.daemon = True
    progressbar.start()
    submit_thread.start()
    root.after(20, check_submit_thread)

def check_submit_thread():
    if submit_thread.is_alive():
        root.after(20, check_submit_thread)
    else:
        progressbar.stop()

root = Tk()
frame = ttk.Frame(root)
frame.pack()
progressbar = ttk.Progressbar(frame, mode='indeterminate')
progressbar.grid(column=1, row=0, sticky=W)

ttk.Button(frame, text="Check",
       command=lambda:start_submit_thread(None)).grid(column=0,    row=1,sticky=E)
root.mainloop()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...