简体   繁体   English

单击按钮后如何停止Tkinter GUI冻结?

[英]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. 这次,它在Python 2.7上与Tkinter一起使用。 The issue at hand is every time the "submit" button I created is pressed, the GUI freezes. 当前的问题是每次按下我创建的“提交”按钮时,GUI都会冻结。 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. 我面临的问题是与GUI一起运行的程序是计时器上永无休止的自动化循环。 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. 此外,由于我很难找到并清除有关如何进行GUI程序的信息,而无需说“嘿...因为我这么说就这样做”,因此将非常感谢您与一些学习/参考资料的链接。

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! 谢谢你们!

the reason your Tk GUI freezes is because you have everything running on 1 thread. 您的Tk GUI冻结的原因是因为您所有内容都在1个线程上运行。 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. mainloop循环受到submit功能调用的困扰,该调用必须花费“很长时间”,因此单击该按钮时,您可能会在Tk窗口中看到“无响应”。 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. 要解决此问题,您需要生成一个单独的线程以供submit运行,以便mainloop可以继续执行此操作并防止Tk窗口冻结。

this is done using threading . 这是使用threading完成的。 Instead of your button directly calling submit , have the button call a function that starts a new thread which then starts submit . 相反,你的按钮直接调用submit ,有按钮调用来启动一个新的线程,然后启动功能submit Then create another functions which checks on the status of the submit thread. 然后创建另一个函数来检查submit线程的状态。 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM