我有一个程序,它每秒钟响一次,直到停止。问题是,在我按下“开始”并发出嘟嘟声后,我无法单击“停止”按钮,因为窗口冻结。欢迎任何帮助。
#!/usr/bin/python
import Tkinter, tkMessageBox, time, winsound, msvcrt
running = True
Freq = 2500
Dur = 150
top = Tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200
def start():
sec = 0
while running:
if sec % 1 == 0:
winsound.Beep(Freq, Dur)
time.sleep(1)
sec += 1
def stop():
running = False
startButton = Tkinter.Button(top, height=2, width=20, text ="Start", command = start)
stopButton = Tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)
startButton.pack()
stopButton.pack()
top.mainloop()
问题是start()
中的while循环阻塞了GUI处理程序mainloop()
。尝试使用Tk。在<代码>开始()中的()之后
:
def start(force=True):
global running
if force:
running = True
if running:
winsound.Beep(Freq, Dur)
top.after(1000, start, False)
并更改Stop()
:
def stop():
global running
running = False
您的代码有顶部。mainloop()。所以这就像是循环中的循环。
您可以创建一个函数,该函数对循环主体执行您想要的操作。它应该对循环进行一次迭代。一旦完成,它需要安排在将来的某个时候使用
之后的再次调用它自己。未来多远定义了循环运行的速度。
然后,您可以在取消后使用
来取消事件。下面的代码对我有用
import Tkinter, tkMessageBox, time, winsound, msvcrt
Freq = 2500
Dur = 150
top = tkinter.Tk()
top.title('MapAwareness')
top.geometry('200x100') # Size 200, 200
def start():
global job1
if running == True:
winsound.Beep(Freq, Dur)
job1 = top.after(1000, start) # reschedule event in 1 seconds
def stop():
global job1
top.after_cancel(job1)
startButton = tkinter.Button(top, height=2, width=20, text ="Start", command = start)
stopButton = tkinter.Button(top, height=2, width=20, text ="Stop", command = stop)
startButton.pack()
stopButton.pack()
#top.after(1000, start)
top.mainloop()
您的代码有几个错误。首先,您不应该在Tkinter程序中使用time.sleep()
,因为它会干扰main循环()
。相反,人们通常使用通用的小部件方法。在()之后
来安排函数在指定的延迟后运行。
其次,您没有正确使用全局变量。当您为函数中的命名变量赋值时,它将创建一个局部变量,除非该名称之前已声明为global
。例如,您的stop()
函数正在创建一个名为的局部变量,运行
并将其值设置为0,而不是更改同名全局变量的值。
前面的规则不适用于仅引用(读取)变量的当前值。这就是为什么在
start()
中没有声明Freq
和Dur
全局变量是可以的。
另一个问题是
start()
函数中的sec%1==0
。任何值%1
都是0
。要检查奇数/均匀度,请使用秒%2
。
这是一个工作版本,它也被重新格式化,以更紧密地遵循PEP8风格的Python代码指南。
try:
import tkinter as tk
except ModuleNotFoundError:
import Tkinter as tk # Python 2.
import time
import winsound
FREQ = 2500
DUR = 150
after_id = None
secs = 0
def beeper():
global after_id
global secs
secs += 1
if secs % 2 == 0: # Every other second.
winsound.Beep(FREQ, DUR)
after_id = top.after(1000, beeper) # Check again in 1 second.
def start():
global secs
secs = 0
beeper() # Start repeated checking.
def stop():
global after_id
if after_id:
top.after_cancel(after_id)
after_id = None
if __name__ == '__main__':
top = tk.Tk()
top.title('MapAwareness')
top.geometry('200x100')
startButton = tk.Button(top, height=2, width=20, text="Start", command=start)
stopButton = tk.Button(top, height=2, width=20, text="Stop", command=stop)
startButton.pack()
stopButton.pack()
top.mainloop()
由于这个答案已经变得相当流行,我想谈谈另一个稍微更高级的话题——即如何让代码更加面向对象,从而通过消除几乎所有全局变量来简化事情。
try:
import tkinter as tk
except ModuleNotFoundError:
import Tkinter as tk # Python 2.
import time
import winsound
FREQ = 2500
DUR = 150
class Application(tk.Frame, object):
def __init__(self, master=None):
super(Application, self).__init__(master) # Call baseclass constructor.
self.after_id = None
self.secs = 0
# Create widgets,
startButton = tk.Button(top, height=2, width=20, text="Start", command=self.start)
stopButton = tk.Button(top, height=2, width=20, text="Stop", command=self.stop)
startButton.pack()
stopButton.pack()
def beeper(self):
self.secs += 1
if self.secs % 2 == 0: # Every other second.
winsound.Beep(FREQ, DUR)
self.after_id = top.after(1000, self.beeper) # Check again in 1 second.
def start(self):
self.secs = 0
self.beeper() # Start repeated checking.
def stop(self):
if self.after_id:
top.after_cancel(self.after_id)
self.after_id = None
if __name__ == '__main__':
top = tk.Tk()
app = Application()
app.master.title('MapAwareness')
app.master.geometry('200x100')
app.mainloop()
启动无限循环后,我无法关闭JFrame。 我想停止无限循环使用停止按钮。 我用开始按钮开始一个无限循环。我想用“停止”按钮关闭那个回路。 > if(stop.getModel(). isP的()){中断;}不工作 actionListener用于识别按钮单击并在循环也不起作用时使用中断语句终止 点击停止按钮,无限循环必须终止。在使用start Button启动无限循环后,我无法使用JFrame中的
问题内容: 因此,我有一个Tkinter GUI,其中有两个简单的选项,即开始和停止按钮。我已经定义了GUI布局: 此处的“开始”按钮运行无限循环扫描,而“停止”按钮在按下时应会中断: 但是,当我按下“开始”按钮时,它总是被按下(假定由于无限循环)。但是,我 无法单击“停止”按钮 来打破while循环。 问题答案: 您不能在Tkinter事件循环所处的同一线程中启动循环。这样做将阻塞Tkinter
问题内容: 我正在编写代码以确定nxn列表中的每个元素是否相同。即返回true,但将返回false。我正在考虑编写一个代码,当它发现与第一个元素不同的元素时立即停止。即: 我想停止此循环, 然后返回false。否则返回true。我将如何实施呢? 问题答案: 使用和为此。可以使用以下命令在Python中完成打破嵌套循环的操作: 另一种方法是将所有内容包装在函数中,并用于从循环中退出。
问题内容: 我试图用图像精灵建立一个加载指示器,然后我想到了这个功能 所以输出看起来像这样 我不得不使用setBgPosition(); 在其他内部保持循环运行,所以现在我的问题是一旦我想要[加载完成],如何停止该循环? 问题答案: 返回计时器句柄,您可以使用该句柄停止超时。 因此,例如: 因此,您可以将其用作: 请注意,我没有将其再次调用,而是将其重新设置为。否则,这将行不通。另请注意,我已将超
我正在使用python创建一个控制Tkinter窗口的类对象。我的代码如下所示: 我希望能够启动一个类的实例,然后像这样停止它: 一切正常,窗口在上成功创建,单击按钮并执行时窗口消失。问题是主循环继续运行。我必须使用Ctrl C手动杀死程序,它显示它在。 如果我只是在一个普通的文件中而不是在一个类中执行所有tkinter代码,那么一切都是一样的,但是当我在root上调用destroy时,mainl
问题内容: 我想如果用户按下主页按钮,我的服务将停止,这是我的代码,但对我不起作用,请帮助我: 谢谢 问题答案: 如果您试图确保该服务仅在相关活动可见时运行,则更好的解决方案是在用户正在运行的任何活动的onPause()方法中停止该服务。这样,当用户按下“返回”时和当用户按下“主页”时,将处理事件。 同样,您可以将服务绑定到一个或多个活动。当绑定到绑定服务的所有活动停止时,绑定服务将被销毁。