在python 2.7中,如果我在循环运行时单击一个按钮,IDLE将停止工作直到python退出循环。我已经附上了我的整个代码,因为我不知道为什么会这样。
import time
import Tkinter as tk
from Tkinter import StringVar
import threading
x="False"
def xval(*args):
for i in range(0,9):
global x
if(x=="False"):
print "x=false %d time"%i
time.sleep(1)
def stop(event):
resume_btn.configure(state="normal")
global x
x ="True"
print "execution stopped:%s"%x
def start(event):
global x
x ="False"
print "execution started:%s"%x
xval()
root = tk.Tk()
th = threading.Event()
t = threading.Thread(target=xval,args=(th,))
t.deamon=True
t.start()
x_btn = tk.Button(root, text="Stop", background="Snow", width=20)
x_btn.grid(row=0, column=4, sticky="W", padx=20, pady=5)
x_btn.bind('<Button-1>',stop)
resume_btn = tk.Button(root, text="Start", background="Snow", width=20)
resume_btn.configure(state="disabled")
resume_btn.grid(row=0, column=6, sticky="W", padx=20, pady=5)
resume_btn.bind('<Button-1>',start)
root.mainloop()
这里两个按钮在第一次运行时工作正常,但第二次当我点击停止时,x的值都没有更新,也没有按钮工作直到python退出循环。谁能说出为什么会发生这种情况。
答案 0 :(得分:1)
是的,程序在执行任何其他操作之前执行for()。为了绕过它,你将不得不使用一些可以被线程和主程序实时共享的容器来停止中间的for()(在Multiprocessing中它是一个管理器字典或列表,不知道它在Threading中是什么样的,或者在方法之后使用Tkinter做类似于下面代码的事情,该代码使用可以在类中看到和使用的类实例对象/属性(此代码中的变量)。 http://www.tutorialspoint.com/python/python_classes_objects.htm
import Tkinter as tk
class StartStop():
def __init__(self, root):
self.x="False"
self.ctr=0
x_btn = tk.Button(root, text="Stop", background="Snow", width=20)
x_btn.grid(row=0, column=4, sticky="W", padx=20, pady=5)
x_btn.bind('<Button-1>', self.stop)
self.resume_btn = tk.Button(root, text="Start", background="Snow", width=20)
self.resume_btn.configure(state="disabled")
self.resume_btn.grid(row=0, column=6, sticky="W", padx=20, pady=5)
self.resume_btn.bind('<Button-1>', self.start)
def xval(self):
if self.x=="False":
print "x=false %d=counter value"%self.ctr
self.ctr += 1
if self.ctr < 9:
## after gives the program time to update
## time.sleep() stops everyting
root.after(1000, self.xval)
def stop(self, event):
self.resume_btn.configure(state="normal")
self.x ="True"
print "execution stopped:%s"%self.x
def start(self, event):
self.x ="False"
print "execution started:%s"%self.x
self.ctr=0
self.xval()
root = tk.Tk()
S=StartStop(root)
root.mainloop()
答案 1 :(得分:1)
只需要在循环结束时使用variable.get()和set()以及root.update()。
import time
import Tkinter as tk
from Tkinter import StringVar
import threading
global root
root = tk.Tk()
x = tk.StringVar()
x.set('false')
def xval(*args):
try:
for i in range(0,9):
global x
print x.get()
if x.get()== 'false' :
print "x=false %d time"%i
time.sleep(1)
else:
print "waiting"
root.update()
except:
pass
def stop(event):
resume_btn.configure(state="normal")
global x
x.set('true')
print "execution stopped:%s"%x
def start(event):
global x
x.set('false')
print "execution started:%s"%x
xval()
root.title("GUI-Data Retrieval")
th = threading.Event()
t = threading.Thread(target=xval,args=(th,))
t.deamon=True
t.start()
x_btn = tk.Button(root, text="Stop", background="Snow", width=20)
x_btn.grid(row=0, column=4, sticky="W", padx=20, pady=5)
x_btn.bind('<Button-1>',stop)
resume_btn = tk.Button(root, text="Start", background="Snow", width=20)
resume_btn.configure(state="disabled")
resume_btn.grid(row=0, column=6, sticky="W", padx=20, pady=5)
resume_btn.bind('<Button-1>',start)
root.mainloop()
但我会说课程是更好的方法:)