所以我有一个Tkinter图形用户界面,有两个简单的选项,一个开始和停止按钮。我已经定义了GUI布局:
from Tkinter import *
def scanning():
while True:
print "hello"
root = Tk()
root.title("Title")
root.geometry("500x500")
app = Frame(root)
app.grid()
在这里,开始按钮运行无限循环扫描,按下时停止按钮应断开:
start = Button(app, text="Start Scan",command=scanning)
stop = Button(app, text="Stop",command="break")
start.grid()
stop.grid()
但是,当我按下开始按钮时,它总是被按下(假设是因为无限循环)。但是,我不能单击“停止”按钮来跳出while循环。
不能在Tkinter事件循环正在运行的同一线程中启动
while True:
循环。这样做会阻塞Tkinter的循环并导致程序冻结。对于一个简单的解决方案,您可以使用^{} 每隔一秒左右在后台运行一个进程。以下是演示脚本:
当然,您可能希望将此代码重构为一个类,并将} module 将是有益的,这样您的
running
作为其属性。另外,如果您的程序变得很复杂,那么查看Python的^{scanning
函数就可以在单独的线程中执行。另一种解决方案是创建执行该功能的可执行文件,while不是while true,而是从外部读取的条件(例如,使用pickle的二进制文件)
因此,在GUI中有一个按钮调用方法pause。它修改文件'condition.p'的内容,从而修改所需的循环
这里有一个不同的解决方案,具有以下优点:
不需要手动创建单独的线程
不使用
Tk.after
调用。相反,保留了具有连续循环的原始代码样式。这样做的主要优点是,您不必手动指定确定循环内代码运行频率的毫秒数,只要硬件允许,它就可以正常运行。注意:我只在python 3中尝试过,而不是在python 2中。我想在python 2中也应该如此,我只是不能百分之百确定。
对于UI代码和开始/停止逻辑,我将使用与iCodez的答案中基本相同的代码。一个重要的区别是,我假设我们将始终运行一个循环,但根据最近按下的按钮决定在该循环中执行什么操作:
在这段代码中,我们不会调用
root.mainloop()
让tkinter GUI不断更新。相反,我们经常手动更新它(在本例中,每500次循环迭代)。理论上,这意味着我们可能不会在按下停止按钮后立即停止循环。例如,如果在我们按下停止按钮的确切时刻,我们处于迭代501,则此代码将继续循环,直到迭代1000被命中为止。因此,这段代码的缺点是,我们在理论上有一个响应速度很慢的GUI(但是如果循环中的代码速度很快,它就不会被注意到)。作为回报,我们让循环中的代码以尽可能快的速度运行(只是有时会有来自GUI
update()
调用的开销),并让它在主线程中运行。相关问题 更多 >
编程相关推荐