2013-02-04 14 views
12

ではないですが、私ははRuntimeError:メインスレッドは、私は私のPythonプログラムで</p> <pre><code>self.client = ThreadedClient() </code></pre> <p>を呼び出すメインループ

"RuntimeError: main thread is not in main loop"

は、私はすでにいくつかのグーグルを行っているエラーを取得しますが、私は作っていますどういうわけか...誰かが私を助けてくれますか?

全エラー:

Exception in thread Thread-1: 
    Traceback (most recent call last): 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 530, in __bootstrap_inner 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 483, in run 
    File "/Users/Wim/Bird Swarm/bird_swarm.py", line 156, in workerGuiThread 
    self.root.after(200, self.workerGuiThread) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 501, in after 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1098, in _register 
    RuntimeError: main thread is not in main loop 

クラス:

class ThreadedClient(object): 

    def __init__(self): 
     self.queue = Queue.Queue() 
     self.gui = GuiPart(self.queue, self.endApplication) 
     self.root = self.gui.getRoot() 
     self.running = True 
     self.GuiThread = threading.Thread(target=self.workerGuiThread) 
     self.GuiThread.start() 

    def workerGuiThread(self): 
     while self.running: 
      self.root.after(200, self.workerGuiThread) 
      self.gui.processIncoming()  

    def endApplication(self): 
     self.running = False 

    def tc_TekenVogel(self,vogel): 
     self.queue.put(vogel) 

class GuiPart(object): 
    def __init__(self, queue, endCommand): 
     self.queue = queue 
     self.root = Tkinter.Tk() 
     Tkinter.Canvas(self.root,width=g_groottescherm,height=g_groottescherm).pack() 
     Tkinter.Button(self.root, text="Move 1 tick", command=self.doSomething).pack() 
     self.vogelcords = {} #register of bird and their corresponding coordinates 

    def getRoot(self): 
     return self.root 

    def doSomething(): 
     pass #button action 

    def processIncoming(self): 
     while self.queue.qsize(): 
      try: 
       msg = self.queue.get(0) 
       try: 
        vogel = msg 
        l = vogel.geeflocatie() 
        if self.vogelcords.has_key(vogel): 
         cirkel = self.vogelcords[vogel] 
         self.gcanvas.coords(cirkel,l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel)    
        else: 
         cirkel = self.gcanvas.create_oval(l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel,fill='red',outline='black',width=1) 
         self.vogelcords[vogel] = cirkel 
        self.gcanvas.update() 
       except: 
        print('Failed, was van het type %' % type(msg)) 
      except Queue.Empty: 
       pass 
+0

トレースバックからは、実行のメインスレッドからではなく、他の場所に作成しているスレッドから 'workerGuiThread'を実行しているようです。私はTKのエキスパートではありませんが、エラーはこれが許可されていないことを示唆しているようです(メインスレッドを使って 'after'のようなTK関数を呼び出す必要があります)。 – Blckknght

+0

[この質問](http://stackoverflow.com/questions/3567238/i-need-a-little-help-with-python-tkinter-and-threading)、[この回答](http:// stackoverflow .com/a/10556698/908494)など、マルチスレッドプログラムでのTkInterの使用に関するいくつかの詳細については、こちらをご覧ください。しかし、短いバージョンです:メインスレッドでのみ、期間を使用します。 – abarnert

+0

Hey Blckknght。そのため私はmtTkinterを使用しています。 – user2040823

答えて

17

あなたがメインスレッド以外のスレッドであなたのメインのGUIのループを実行しています。あなたはこれをすることはできません。

Tkinterはスレッドセーフではありませんが、私の知る限り、決して出てこないと主なスレッドからTkとしか話せないと言います。理由は、真実はやや複雑だからです。 Tkinter自体スレッドセーフですが、マルチスレッドの方法では使いにくいです。この上の公式ドキュメントに最も近いthis pageのようだ:

Q. Is there an alternative to Tkinter that is thread safe?

Tkinter?

Just run all UI code in the main thread, and let the writers write to a Queue object…

(与えられたサンプルコードは素晴らしいではありませんが、それは、彼らが示唆されているかを把握し、適切に物事を行うには十分です。)

実際には、で、Tkinterの代わりにスレッドセーフであるmtTkinterです。そして、そのドキュメントは実際にはかなりうまく状況を説明:

Although Tkinter is technically thread-safe (assuming Tk is built with --enable-threads), practically speaking there are still problems when used in multithreaded Python applications. The problems stem from the fact that the _tkinter module attempts to gain control of the main thread via a polling technique when processing calls from other threads.

私は、これはあなたが見ている正確に何であると信じて:あなたのTkinterのコードをスレッド-1でメインループを見つけるために、メインスレッドに覗き見しようとしている、とそこにはありません。

ので、ここでいくつかのオプションがあります

  • はTkinterのドキュメントをお勧めします何をすべきか、メインスレッドからのTkinterを使用しています。おそらくあなたの現在のメインスレッドコードをワーカースレッドに移動することによって可能性があります。
  • メインスレッド(例えばtwisted)を引き継ぐ他のライブラリを使用している場合は、Tkinterと統合する方法があるかもしれません。その場合は、それを使用する必要があります。
  • mkTkinterを使用して問題を解決してください。

また、この質問の正確な重複は見つかりませんでしたが、SOに関する多くの関連する質問があります。詳細については、this question,this answerなどを参照してください。

+0

こんにちは。ご回答有難うございます。私はmtTkinterでこのオプションを使用しました。私のコードは実行中です(エラーはありません)。しかし、私はキャンバスを見ることができません...ロギングでは、私はプログラムが動作している参照してください...視覚化せずにのみ。 @ https://github.com/wimhendrickx/Flocking/blob/master/bird_swarm.pyというコードは表示されません。前もって感謝します。 – user2040823

+0

@ user2040823:白い背景に白い文字で表示されているのはなぜですか? :)とにかく、私はそれをダウンロードして見てみましょう。 – abarnert

+0

@ user2040823:OK、ここにはいくつかの基本的な問題があります。まず、あなたは 'root.mainloop()'をどこでも呼び出さない。次に、 'doSomething'のような' self'を取らないメソッド(staticメソッドではないメソッド)があります。第三に、 'Tkinter'イベントハンドラは' event'パラメータを取っていません。私はあなたがそれの周りで複雑なものを構築しようとする前に、そして/またはmtTkinterを使う前に、基本的なTkinterチュートリアルで作業する必要があると思います。あなたが答えを見つけることができない特定の質問がある場合は、新しい質問を作成しますが、私はSOのコメントでTkinterの基礎を教えていません。 – abarnert

関連する問題