2012-09-06 21 views
1

我正計劃圍繞數值模擬編寫一個小GUI,這就是爲什麼我現在正在玩弄Tkinter。模擬應該在獨立進程中從GUI啓動。爲了玩一下,我定義了一個函數random_process,它生成一對randn數字(這應該是一個真正的模擬過程)。由於該函數旨在在單獨的進程中啓動,因此將兩個mp.Event對象和一個mp.Pipe對象作爲參數傳遞。 主應用程序可以使用一個事件來請求過程中的累積數據,另一個事件被用作「毒丸」來殺死「模擬」過程。然後使用管道傳遞數據。 在主應用程序中,我使用Tkinter的函數後定期檢查新數據是否已到達,然後繪製它。啓動和停止「模擬過程」是通過主應用程序中的按鈕完成的,從數據中請求數據也是如此。Tkinter:通過多處理啓動過程創建了不想要的新窗口

至少這是這個想法,在實踐中,該程序不會很好。當我點擊「去!」按鈕是爲了啓動仿真過程,第二個Tkinter窗口出現,與主窗口相同。我絲毫不知道爲什麼會發生這種情況。與流程的溝通也不起作用,似乎沒有數據發送。當搜索一個解決方案時,我發現了一個Tkinter程序的工作示例,啓動過程並與他們交談,但我沒有發現是什麼讓我無法正常工作。有人有線索嗎?

順便說一下,OS是Windows-7。

乾杯, 揚

import matplotlib 
matplotlib.use('TkAgg') 
import time 
import multiprocessing as mp 
import Tkinter as Tk 
import numpy.random as npr 
import matplotlib.figure 
import matplotlib.backends.backend_tkagg as tkagg 

def random_process(delay, data_request, data_in, poison): 
    while not poison.is_set(): 
     time.sleep(delay) 
     print("Generating pair of random numbers...") 
     x,y = npr.randn(), npr.randn() 
     try: 
      random_process.l.append((x,y)) 
     except: 
      random_process.l = [(x,y)] 
     if data_request.is_set(): 
      data_request.clear() 
      try: 
       ll = len(random_process.l) 
       if ll > 0: 
        print("Sending %d pairs to main program.." % ll) 
        data_in.send(random_process.l) 
       random_process.l = [] 
      except: 
       print("data requested, but none there.") 
    # when poison event is set, clear it: 
    poison.clear() 

class GuiInterfaceApp: 
    def __init__(self, parent): 
     self.myParent = parent 

     self.previewplot_container = Tk.Frame(self.myParent) 
     self.f = matplotlib.figure.Figure() 
     self.ax = self.f.add_subplot(111) 
     self.preview_canvas = tkagg.FigureCanvasTkAgg(self.f, master=self.previewplot_container) 
     self.preview_canvas.show() 

     self.button_container = Tk.Frame(self.myParent) 
     self.hellobutton = Tk.Button(self.button_container, text="hello!") 
     self.hellobutton.config(command = self.printhello) 
     self.startbutton = Tk.Button(self.button_container, text="go!") 
     self.startbutton.config(command=self.run_simulation) 
     self.plotbutton = Tk.Button(self.button_container, text="show!") 
     self.plotbutton.config(command=self.request_data) 
     self.stopbutton = Tk.Button(self.button_container, text="stop.") 
     self.stopbutton.config(command=self.stop_simulation) 
     self.quitbutton = Tk.Button(self.button_container, text="get me outta here!") 
     self.quitbutton.config(command=self.quit_program) 

     self.previewplot_container.pack(side = Tk.TOP) 
     self.preview_canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) 
     self.button_container.pack(side = Tk.BOTTOM) 
     self.hellobutton.pack(side = Tk.LEFT) 
     self.startbutton.pack(side = Tk.LEFT) 
     self.plotbutton.pack(side = Tk.LEFT) 
     self.stopbutton.pack(side = Tk.LEFT) 
     self.quitbutton.pack(side = Tk.LEFT) 

     self.simulation_running = False 

     self.datarequest = mp.Event() 
     self.DataIn, self.DataOut = mp.Pipe() 
     self.PoisonEvent = mp.Event() 
     self.p = mp.Process(target = random_process, args=(1.0, self.datarequest,  self.DataIn, self.PoisonEvent)) 

     self.l = [] # list of received pairs to plot 

     self.mytask_time = 100 # delay in ms between calls to self.mytask 

    def printhello(self): 
     print("hello!") 

    def run_simulation(self): 
     print("startbutton pressed.") 
     if not self.simulation_running: 
      print("starting simulation...") 
      self.p.start() 
      self.simulation_running = True # attention: no error checking 

    def stop_simulation(self): 
     print("stop button pressed.") 
     if self.simulation_running: 
      print("Sending poison pill to simulation process..") 
      self.PoisonEvent.set() 
      self.simulation_running = False 
      # todo: wait a short amount of time and check if simu stopped. 

    def request_data(self): 
     print("plotbutton pressed.") 
     if self.simulation_running: 
      print("requesting data from simulation process") 
      self.datarequest.set() 

    def update_plot(self): 
     print("update_plot called.") 
     if len(self.l) > 0: 
      print("there is data to plot.") 
      while len(self.l) > 0: 
       x,y = self.l.pop() 
       print("plotting point (%.2f, %.2f)" % (x,y)) 
       self.ax.plot([x], [y], '.', color='blue') 
      print("drawing the hole thing..") 
      self.ax.draw() 
     else: 
      print("nothing to draw") 

    def quit_program(self): 
     print("quitbutton pressed.") 
     if self.simulation_running: 
      print("sending poison pill to simulation process..") 
      self.PoisonEvent.set() 
     print("quitting mainloop..") 
     self.myParent.quit() 
     print("destroying root window..") 
     self.myParent.destroy() 

    def receive_data(self): 
     if self.DataOut.poll(): 
      print("receiving data..") 
      data = self.DataOut.recv() 
      self.l.append(data) 
      self.update_plot() 

    def my_tasks(self): 
     self.receive_data() 
     self.myParent.after(self.mytask_time, self.my_tasks) 
     return 

root = Tk.Tk() 
myGuiInterfaceApp = GuiInterfaceApp(root) 
root.after(100, myGuiInterfaceApp.my_tasks) 
root.mainloop() 
+0

請注意,從'object'繼承你的類。在Python 2.x中不要只做「class name:」 – jsbueno

回答

1

嘗試隱藏你的測試背後的主要邏輯代碼是否正在運行或進口。

if __name__ == "__main__": 
    root = Tk.Tk() 
    ... 
+0

非常感謝,就是這樣! – jan

相關問題