终于得到了我的第一个线程脚本"有点"在各种教程和在线参考之间来回奔跑。 "有点"因为我在启动时仍然会遇到一些奇怪的错误。
我的计划目标
在这个简化的调试实现中,你会看到我似乎不必要地使用了spinbox控件变量。控制变量的实际(较长程序)应用于触发用户输入到旋转框中的验证程序。它实际上是控制变量,它给了我一些好奇的错误"在程序启动期间
我的简化代码如下:
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")
问题1:
class controlThread.towardsTarget()
print
声明中
引用self.ctrlVar
每次程序都会引起错误
开始。错误是&#34; RuntimeError:主线程不在main中
环路&#34; controlPanel.goButton
)仍将提供该程序
上面指定的行为(即后续点击&#34; Go&#34;按钮时没有更多错误)问题2:
print
语句放在a中时
lock.acquire()/lock.release()
阻止,点击&#34; Go&#34;按键
(controlPanel.goButton
)将冻结程序我已阅读以下两页和相关链接
但是上面两页中提到的解决方案对我来说没有多大意义,因为错误信息&#34; RuntimeError:主线程不在主循环中#34;如果引用print
引用self.ctrlVar
语句完全被删除,则根本不会出现。
我的问题是
lock.acquire()/lock.release()
块能够解决
问题,但它最终冻结了程序。怎么能
打印&#39;可以避免这个问题。语句引用
self.ctrlVar
到位了吗?