我一直有困難與多線程和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 =
不同的功能。
我也試圖與拉姆達的解決方案爲這樣:
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
我希望它通過after
聲明中調用self.periodiccall
。至少,這是我認爲正在發生的事情。如何在這個遞歸函數中刪除這個錯誤並使widget成爲一個變量?
完美。這正是我需要的。我正在使用lambdas,因爲我希望能夠將spawnthread,periodicall和threadedclient轉儲到我的窗口小部件模板模塊中以實現代碼的清潔。 –
我有一個後續問題;我將它添加到原始問題中。 –