2013-06-19 71 views
4

我是python的初學者,它是我的第一語言。我的任務是快速變得太大,以致於無法掌握我需要完成的事情。我快完成了。此時,我創建了一個對話框作爲主菜單,一個對話框是運行測試的主菜單中的一個可選選項,以及一個運行測試的多線程實例,打開「請稍候」在完成測試後,彈出另一個對話框,聲明測試已完成。Tkinter:調用多線程實例

我的問題:在「運行測試」對話框中,我試圖創建一個按鈕,將多線程實例調用到行動中。從我已經在其他人的幫助下解析的代碼中,我看不到在「運行測試」對話框中要實例化哪個類。

我開始相信我的線程實現是不正確的。但是一定有辦法。

這是我試圖調用的模塊。

from slice_setup import SLICE_SETUP 
import Tkinter as tk 
import threading 
import Queue 


class GuiPart: 
    def __init__(self, master, queue): 
     self.queue = queue 
     self.master = master 
     self.master.geometry("300x100+400+250") 
     self.master.title("RSAM BCT") 
     tk.Label(master, text="REDCOM SLICE", fg="red").pack() 
     tk.Label(master, text="BCT - Basic Configuration Test", fg= "red").pack() 
     tk.Label(master, text="Please wait...", fg= "black").pack() 
     tk.Label(master, text="Estimated time: 3 min 6 sec", fg= "black").pack() 

    def processIncoming(self): 
     while self.queue.qsize(): 
      try: 
       text = self.queue.get(0) 
       Complete(self.master, text) 
      except Queue.Empty: 
       pass 

class ThreadedClient: 
    def __init__(self, master): 
     self.master = master 
     self.queue = Queue.Queue() 
     self.gui = GuiPart(master, self.queue) 
     self.running = True 
     self.thread = threading.Thread(target=self.workerThread1) 
     self.thread.start() 
     self.periodicCall() 

    def periodicCall(self): 
     self.gui.processIncoming() 
     if not self.running: 
      return 
     self.master.after(100, self.periodicCall) 

    def workerThread1(self): 
     obj_rcs = SLICE_SETUP() 
     obj_rcs.SLICE() 
     self.queue.put("Configuration Complete!") 
     self.running = False 

class Complete(tk.Toplevel): 
    def __init__(self, master=None, completetext=""): 
     tk.Toplevel.__init__(self, master) 
     self.geometry("400x300+400+250") 
     self.title("RSAM BCT") 
     tk.Label(self, text="REDCOME SLICE", fg="red").pack() 
     tk.Label(self, text="BCT - Basic Configuration Test", fg="red").pack() 
     tk.Label(self, text=completetext, fg="dark green").pack() 
     tk.Label(self, text="Trunk 1: Port 1: Phone 1: 760-450-4500", fg="black").pack() 
     tk.Label(self, text="Trunk 1: Port 2: Phone 2: 760-450-4501", fg="black").pack() 
     tk.Button(self, text=" Exit ", command=self.destroy).pack() 


if __name__ == "__main__": 
    root = tk.Tk() 
    client = ThreadedClient(root) 
    root.mainloop() 

而這正是我試圖調用從:

import sys 
import Tkinter as Tk() 
from bct_pleasewait import ???? 
import threading 
import Queue 
import time 
sGui = Tk() 

class slice_menu: 

    def runtest(self): 
     obj_wait = ???? 
     obj_wait.???? 

    def slicemenu(self): 
     sGui.geometry("400x300+400+250") 
     sGui.title("RSAM BCT") 
     Label(sGui, text= "REDCOM SLICE", fg="red").pack() 
     Label(sGui, text= "BCT - Basic Configuration Test", fg= "red").pack() 
     Label(sGui, text= "-Ensure you are logged off of HyperTerminal", fg= "black").pack() 
     Label(sGui, text= "-Turn on your REDCOM SLICE unit", 
     fg= "black").pack() 
     Label(sGui, text= "-Please connect your laptop to SLICE CONSOLE", fg= "black").pack() 
     Label(sGui, text= "-This configuration will take 3 minutes", fg= "black").pack() 
     Button(sGui, text = "  Run  ", command = self.runtest).pack() 
     Button(sGui, text = " Exit test ", command = sGui.destroy).pack() 
     sGui.mainloop() 

這個類還是有小錯誤,但我只是想這個問題解決了第一。

+0

我認爲你必須更準確地說明問題所在。你的問題似乎沒有足夠的動力,我相信這裏的很多人可以很容易地解決你的問題,如果它更清楚一點。 –

回答

0

沒有一個具體的答案,但你的問題是非常廣泛的。

幾點要牢記:

  • Tk的不是線程安全的。也就是說,你應該只有從主線程調用Tk調用。讓其他線程做非GUI工作是可以的。
  • 在CPython中,由於全局解釋器鎖定(「GIL」),一次只能有一個線程正在執行Python字節碼。所以你的非gui線程可能會導致GUI無響應。

如果您一次只運行一個測試,並且如果您可以將該測試分成小塊,則可以使用超時(也稱爲alarm handler)。該處理程序會執行一些工作,保存其狀態,更新進度對話框,然後退出,等待再次調用。

如果測試運行很長時間,並且您希望GUI保持響應,我建議使用multiprocessing而不是線程。在不同的過程中開始測試,並使用Queue和Semaphores等等來進行GUI和非qui過程之間的通信。