4

数値シミュレーションを中心に小さなGUIを作成することを計画しているので、現在Tkinterで遊んでいます。シミュレーションは、別のプロセスでGUIから起動する必要があります。少し遊んでみるために、ランダムな数値のペアを生成する関数random_processを定義しました(これは後で実際のシミュレーションプロセスになるはずです)。この関数は別のプロセスで起動することを目的としているため、2つのmp.Eventオブジェクトと1つのmp.Pipeオブジェクトがパラメーターとして渡されます。メインアプリケーションは、1つのイベントを使用してプロセスから蓄積されたデータを要求でき、別のイベントは「シミュレーション」プロセスを強制終了するための「ポイズンピル」として使用されます。次に、パイプを使用してデータを渡します。メインアプリケーションでは、Tkinterのアフター関数を使用して、新しいデータが到着したかどうかを定期的にチェックし、それをプロットします。「シミュレーションプロセス」の開始と停止

少なくともそれはアイデアでした。実際には、プログラムはうまく機能しません。「go!」をクリックすると シミュレーションプロセスを起動するためのボタンをクリックすると、メインウィンドウと同じ2番目のTkinterウィンドウが表示されます。なぜそうなるのか、私には少しもわかりません。プロセスとの通信も機能せず、データが送信されていないようです。解決策を探しているときに、Tkinterプログラムがプロセスを起動してそれらと話している実例を見つけましたが、私の場合、それが機能しない理由はわかりませんでした。誰か手がかりがありますか?

ところで、OSはWindows-7です。

乾杯、1月

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()
4

1 に答える 1

5

コードが実行されているかインポートされているかをテストするために、メインロジックを非表示にしてみてください。

if __name__ == "__main__":
    root = Tk.Tk()
    ...
于 2012-09-06T12:42:55.990 に答える