我在使用Tkinter(和ttk)和Python將GUI組織成可用且不是超級錯誤的程序時遇到了麻煩。基本上,它只是將圖像從網上下載,但即使是一個簡單的GUI,我也遇到了麻煩。雖然所有的東西都在控制檯中工作,但使GUI成爲一場噩夢,更不用說使其工作。現在,我有它的工作,但它經常崩潰,很明顯,我做錯了錯誤獲取GUI中的變量錯誤沒有被正確訪問(甚至控制檯中的錯誤消息,我已經把自己的功能,以確保事情去正確)和不斷崩潰。如何組織線程化GUI應用程序(Python)
基本上我有這樣的事情。
發生並需要工作的主要事情是:從輸入文本中的用戶輸入字符串發送到程序的密集部分(當前包含在線程中),強化部分步進GUI的進度條,以及密集部分發送文本消息到文本框/記錄器,無需GUI和密集部件崩潰。密集的部分應該在GUI完全加載後立即啓動,並在準備就緒時將啓動消息發送到文本框。
密集部分處理其他事情,但不干擾GUI,例如實際下載和保存圖像,瀏覽和文件I/O,而且大多數情況下我都沒有問題。
我也讀過關於隊列和線程和教程,但我似乎無法得到它。尤其是如何讓程序不斷地在GUI中執行進度條,同時還將文本消息發送到GUI(例如,我甚至可以從隊列接近,而不必執行非常慢且CPU密集型的工作,而如果循環和多個隊列使得它更加瘋狂,簡單的例子中,只需要一個簡單的while和queue.get()等待,因爲它消耗的資源很少)。所以我的問題是,我需要採取什麼樣的結構來實現這個目標,如果可能的話,我可以得到一個或兩個示例(我從示例中學到的東西比從閱讀文檔中學得更好)?非常感謝你。
from Tkinter import *
import ttk
import Threading
import #a bunch of other stuff
class myHardWorkerThread (threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.setDaemon(True)
self.myClass = ModifiedConsoleClass()
def run(self):
#thread needs to wait at least a little otherwise the thread begins too
#fast and causes even more errors, probably due to it sending text to
#the textbox upon startup among other things and just overall no
#organization
time.sleep(3)
self.myClass.BeginDoingStuff()
class ApplyMyGuiAndStartThread():
def __init__(self, root, thread):
root.geometry('500x500')
root.resizable(0,0)
#Put backgrounds or images or logos here
self.canvas = Canvas(root)
self.canvas.pack()
#My textbox that acts like a Log/Console output
self.txtLogger = Text(root,state="disabled",wrap="word")
self.txtLogger.place()
self.scrollbar = Scrollbar(root)
self.scrollbar.place()
#Progressbar
self.myVal = IntVar()
self.TProgressbar = ttk.Progressbar(root, orient=HORIZONTAL, variable = self.myVal, mode='determinate')
self.TProgressbar.place()
#Entrybox for user input
self.txbEntryText = StringVar()
self.txtbEntry = ttk.Entry (root, textvariable=self.txbEntryText)
self.txtbEntry.place()
self.txtbEntry.bind("<Return>", self.SendFromGUItoThread)
self.thread = thread
self.thread.start()
def SendFromGUItoThread(self,arg=None):
myentry = str(self.txtbEntry.get())
self.txtbEntry.delete(0, END)
self.thread.myClass.entryBoxValueCopy = myentry
def SendFromThreadToGUI(self,msg):
try:
self.txtLogger['state'] = 'normal'
self.txtLogger.insert('end', msg)
self.txtLogger['state'] = 'disabled
except:
print "Could not be printed"
class ModifiedConsoleCode():
def __init__(self):
#constants here like
self.entryBoxValueCopy = None
def BeginDoingStuff():
#Thread does the bulk of work here, includes connecting to websites,
#collecting info, sending text messages to GUI, downloading images and
#stepping the progressbar by a calculated amount by file size
def OneOfManyFunctionsUsedInsideBeginDoingStuff():
#Breaks things down like looping time.sleep waits for user input in the entry box
#showing up in entryBoxValueCopy, and using the user input to surf websites and
#collect images
if __name__ == '__main__':
root = Tk()
root.title(titleOfTheProgram)
worker = myHardWorkerThread()
w = ApplyMyGuiAndStartThread(root,worker)
root.mainloop()
os._exit(0)
在這種情況下,我不認爲這會有所幫助 - 問題意味着需要完成一些長時間運行的任務,例如下載圖像。與主循環中的時間片相比,用線程更容易。 –