与spinbox控制变量一起使用时出现Python线程错误
在各种教程和在线参考资料之间来回浏览之后,终于让我的第一个线程脚本“稍微”运行起来。“有点”,因为我在启动过程中仍然会遇到一些奇怪的错误 我的课程目标与spinbox控制变量一起使用时出现Python线程错误,python,multithreading,locking,Python,Multithreading,Locking,在各种教程和在线参考资料之间来回浏览之后,终于让我的第一个线程脚本“稍微”运行起来。“有点”,因为我在启动过程中仍然会遇到一些奇怪的错误 我的课程目标 使用tkinter构建的集成上/下计数器GUI。(Python 3.4.2) Spinbox作为用户入口点-用户输入“目标”整数 或者单击其上/下箭头 当标签上的数字递增时,在标签上显示延迟更新/ 向下,以满足(2)中提到的“目标”整数 当标签上显示的数字等于 目标值 用户输入目标值后,一个“Go”(开始)按钮开始爬升/下降 停止更新的“停止”按
import tkinter as tk
import threading
import time
class controlPanel():
def __init__(self, master):
self.root = master
self.buildWidgets()
def buildWidgets(self):
self.labelVar = 0
self.ctrlVar = tk.StringVar()
self.ctrlVar.set(str(self.labelVar))
self.delay = 0.5
#+++++++++++++++++++++++++++++++++
self.labelName = tk.Label(self.root, text="Current Value: ", padx=3, pady=3)
self.labelName.grid(row=0, column=0)
self.labelValue = tk.Label(self.root, text=str(self.labelVar), padx=3, pady=3)
self.labelValue.grid(row=0, column=1)
#+++++++++++++++++++++++++++++++++
self.spinboxName = tk.Label(self.root, text="Target: ", padx=3, pady=3)
self.spinboxName.grid(row=1, column=0)
self.spinBoxA = tk.Spinbox(self.root, from_=0, to=1000,
textvariable=self.ctrlVar,
width=10, justify=tk.CENTER)
self.spinBoxA.grid(row=1, column=1)
#+++++++++++++++++++++++++++++++++
self.goButton = tk.Button(self.root, text="Go", width=12,
command=self.goButtonFunction,
padx=3, pady=3)
self.goButton.grid(row=2, column=1)
#+++++++++++++++++++++++++++++++++
self.stopButton = tk.Button(self.root, text="Stop", width=12,
command=self.stopButtonFunction,
padx=3, pady=3)
self.stopButton.grid(row=2, column=0)
#+++++++++++++++++++++++++++++++++
#self.labelValue.update()
#self.spinBoxA.update()
self.root.update()
def goButtonFunction(self):
print('GO button clicked')
self.flgRun = True
def stopButtonFunction(self):
print('STOP button clicked')
self.flgRun = False
class controlThread(controlPanel):
def __init__(self, master, name):
self.root = master
self.name = name
controlPanel.__init__(self, self.root)
self.flgRun = False
self.flgRunLock = threading.Lock()
self.pollPeriod = 100 # polling period, in ms
self.thread1 = threading.Thread(target = self.towardsTarget,
name=self.name)
self.thread1.daemon = False
self.thread1.start()
#time.sleep(5)
self.pollFlgRun()
#+++++++++++++++++++++++++++++++++
def pollFlgRun(self): # polls self.flgRun every self.pollPeriod
if self.flgRun:
print('<< Entering pollFlgRun >>')
time.sleep(0.01)
self.towardsTarget()
#self.flgRunLock.acquire() # lock thread to reset self.flgRun
self.flgRun = False # reset self.flgRun
#self.flgRunLock.release() # release thread
self.root.after(self.pollPeriod, self.pollFlgRun)
#+++++++++++++++++++++++++++++++++
def towardsTarget(self):
delay = 0.01 # delay in seconds
time.sleep(delay)
print('<< Entering towardsTarget >>')
#self.flgRunLock.acquire()
print('self.labelVar : ', str(self.labelVar))
# Problem 1: the following reference to self.ctrlVar gave error everytime the
# program starts. The error>> "RuntimeError: main thread is not in main loop"
# subsequent click on controlPanel.goButton will still give the program behavior
# specified above (i.e. no more error on subsequent clicks on the "Go" button)
#
# Problem 2: and when placed in a lock.acquire()/release() block, clicking the
# controlPanel.goButton will freeze up program
print('self.ctrlVar : ', self.ctrlVar.get())
#self.flgRunLock.release()
# test self.flgRun as well in case reset by controlPanel.stopButton
while( self.flgRun and str(self.labelVar) != self.ctrlVar.get() ):
print('WHILE loop')
if( self.labelVar < int(self.ctrlVar.get()) ):
self.labelVar +=1
print('self.labelVar before sleep> ', self.labelVar)
time.sleep(delay)
print('self.labelVar AFTER sleep> ', self.labelVar)
self.labelValue["text"] = str(self.labelVar)
self.labelValue.update()
else:
self.labelVar -=1
print('self.labelVar before sleep> ', self.labelVar)
time.sleep(delay)
print('self.labelVar AFTER sleep> ', self.labelVar)
self.labelValue["text"] = str(self.labelVar)
self.labelValue.update()
if __name__ == '__main__':
root = tk.Tk()
ctrl = controlThread(root, "X-thread")
将tkinter作为tk导入
导入线程
导入时间
类controlPanel():
定义初始(自我,主):
self.root=master
self.buildWidgets()
def buildWidgets(自):
self.labelVar=0
self.ctrlVar=tk.StringVar()
self.ctrlVar.set(str(self.labelVar))
自延迟=0.5
#+++++++++++++++++++++++++++++++++
self.labelName=tk.Label(self.root,text=“当前值:”,padx=3,pady=3)
self.labelName.grid(行=0,列=0)
self.labelValue=tk.Label(self.root,text=str(self.labelVar),padx=3,pady=3)
self.labelValue.grid(行=0,列=1)
#+++++++++++++++++++++++++++++++++
self.spinboxName=tk.Label(self.root,text=“Target:”,padx=3,pady=3)
self.spinboxName.grid(行=1,列=0)
self.spinBoxA=tk.Spinbox(self.root,从0到1000,
textvariable=self.ctrlVar,
宽度=10,对正=tk.中心)
self.spinBoxA.grid(行=1,列=1)
#+++++++++++++++++++++++++++++++++
self.goButton=tk.Button(self.root,text=“Go”,width=12,
命令=self.goButtonFunction,
padx=3,pady=3)
self.goButton.grid(行=2,列=1)
#+++++++++++++++++++++++++++++++++
self.stopButton=tk.Button(self.root,text=“Stop”,width=12,
命令=self.stopButton函数,
padx=3,pady=3)
self.stopButton.grid(行=2,列=0)
#+++++++++++++++++++++++++++++++++
#self.labelValue.update()
#self.spinBoxA.update()
self.root.update()
def GoButton功能(自身):
打印('点击GO按钮')
self.flgRun=True
def停止按钮功能(自身):
打印('单击停止按钮')
self.flgRun=False
类controlThread(控制面板):
定义初始化(自身、主控、名称):
self.root=master
self.name=名称
控制面板。初始化(self,self.root)
self.flgRun=False
self.flgRunLock=threading.Lock()
self.pollPeriod=100#轮询周期,以毫秒为单位
self.thread1=threading.Thread(target=self.towardsTarget,
name=self.name)
self.thread1.daemon=False
self.thread1.start()
#时间。睡眠(5)
self.pollFlgRun()
#+++++++++++++++++++++++++++++++++
def pollFlgRun(self):#每self.pollgrun一次轮询self.flgRun
如果self.flgRun:
打印(“>”)
睡眠时间(0.01)
self.towardsTarget()
#self.flgRunLock.acquire()#锁定线程以重置self.flgRun
self.flgRun=False#重置self.flgRun
#self.flgRunLock.release()#释放线程
self.root.after(self.pollPeriod,self.pollFlgRun)
#+++++++++++++++++++++++++++++++++
def towardsTarget(自):
延迟=0.01#以秒为单位的延迟
时间。睡眠(延迟)
打印(“>”)
#self.flgRunLock.acquire()
打印('self.labelVar:',str(self.labelVar))
#问题1:以下对self.ctrlVar的引用每次都出现错误
#节目开始了。错误>>“RuntimeError:主线程不在主循环中”
#随后单击controlPanel.goButton仍将给出程序行为
#如上所述(即后续点击“Go”按钮时不再出现错误)
#
#问题2:当放置在lock.acquire()/release()块中时,单击
#controlPanel.goButton将冻结程序
打印('self.ctrlVar:',self.ctrlVar.get())
#self.flgRunLock.release()
#在控制面板复位的情况下,也测试self.flgRun.stop按钮
while(self.flgRun和str(self.labelVar)!=self.ctrlVar.get()):
打印(‘WHILE循环’)
if(self.labelVar',self.labelVar)
时间。睡眠(延迟)
打印('self.labelVar AFTER sleep>',self.labelVar)
self.labelValue[“text”]=str(self.labelVar)
self.labelValue.update()
其他:
self.labelVar-=1
打印('self.labelVar before sleep>',self.labelVar)
时间。睡眠(延迟)
打印('self.labelVar AFTER sleep>',self.labelVar)
self.labelValue[“text”]=str(self.labelVar)
自标定值