我在多线程和tkinter方面遇到了困难。 slxl
是我使用的模块,它可以工作,它的函数不返回值(只是为了确保没有混淆。)
以下是 的代码:
#relevant tkinter code
def create_widgets():
self.updatebttn = Button(self, text='Auto Update', command=self.spawnthread)
self.updatebttn.grid(row=1, column=0, sticky=N)
self.progressbar = Progressbar(self, orient='horizontal',
length=300, mode='determinate')
self.progressbar.grid(row=1, column=1, sticky=W)
self.progressbar["maximum"] = (slxl.sizeFinder()) * 1.1
def spawnthread(self):
self.updatebttn.config(state="disabled")
self.thread = ThreadedClient1(self.queue)
self.thread.start()
self.periodiccall()
def periodiccall(self):
if self.thread.is_alive():
self.after(100, self.periodiccall)
self.progressbar.step(500)
else:
self.updatebttn.config(state="active")
self.progressbar.stop()
class ThreadedClient1(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
time.sleep(1)
importer = slxl.runImportAndCoordAdder()
self.queue.put(importer)
问题是,我希望ThreadedClient1能够将它放入队列的函数,在这种情况下slxl.runImportAndCoordAdder()
作为参数,因为我使用ThreadedClient
不止一次使用不同的函数(我以后在程序中只使用不同的函数对它有相同的用法)并且我不喜欢ThreadedClient1
和ThreadedClient2
,唯一的区别是importer =
不同的函数。
我确实尝试过使用lambda的解决方案:
def spawnthread(self):
self.updatebttn.config(state="disabled")
self.thread = ThreadedClient1(self.queue, lambda: slxl.runImportAndCoordAdder())
self.thread.start()
self.periodiccall()
#periodic call is the same
class ThreadedClient1(threading.Thread):
def __init__(self, queue, fcn):
threading.Thread.__init__(self)
self.queue = queue
self.fcn = fcn
def run(self):
time.sleep(1)
self.queue.put(lambda: self.fcn)
这不起作用,因为它忽略了我感兴趣的功能,稍微/禁用了进度条并启用了按钮,然后结束了。
我做错了什么?
修改
问题解决了。然而另一个出现了。我想将spawnthread
,periodiccall
和ThreadedClient
转移到我拥有的小部件模板模块并对其进行概括,以便我可以轻松使用它们。我这样做了:
def spawnthread(self, widget):
widget.config(state="disabled")
self.thread = ThreadedClient1(self.queue)
self.thread.start()
self.periodiccall()
哪个有效,直到我试图概括periodiccall
。
#...
self.periodiccall(widget=widget)
def periodiccall(self, widget=None):
if self.thread.is_alive():
self.after(100, self.periodiccall)
self.progressbar.step(500)
#print widget
else:
widget.config(state="active")
self.progressbar.stop()
我弹出了print widget
,看看自从我一直遇到属性错误后发生了什么。似乎正在发生的事情是,它第一次通过函数运行它知道什么是“小部件”然后它变成了None
我希望通过调用self.periodiccall
来after
1}}陈述。至少,这就是我认为正在发生的事情。如何在此递归函数中删除此错误并使窗口小部件成为变量?
答案 0 :(得分:1)
问题是当你将它用作ThreadedClient1
的参数时,你没有调用该函数:
class ThreadedClient1(threading.Thread):
# ...
def run(self):
time.sleep(1)
self.queue.put(lambda: self.fcn)
它只是一个函数,它返回对作为参数传递的lambda的引用,而不是对slxl.runImportAndCoordAdder()
的调用的结果。它应该是:
class ThreadedClient1(threading.Thread):
# ...
def run(self):
time.sleep(1)
self.queue.put(self.fcn())
或直接引用的另一个解决方案(没有lambdas):
def spawnthread(self):
self.updatebttn.config(state="disabled")
self.thread = ThreadedClient1(self.queue, slxl.runImportAndCoordAdder)
self.thread.start()
self.periodiccall()
class ThreadedClient1(threading.Thread):
# ...
def run(self):
time.sleep(1)
self.queue.put(self.fcn())