2011-12-30 15 views
35

すべてのtkinterチュートリアル私は、ウィンドウが描画され、イベントが処理されるためにはtkinter.mainloopが呼び出されなければならず、hello worldプログラムでも常にこの関数を呼び出しているという主張を見てきました。しかし、対話型シェルでこれらを試してみると、メインループを呼び出さなくてもウィンドウが正しく描画されます。 This exampleは、tkinterにmatplotlibグラフィックスを埋め込むために、比較的複雑なアプリケーションを作成します.Tkinterウィンドウ内のプロットをパン、ズーム、サイズ変更するためのボタンがあります。また、mainloopへの呼び出しを削除してインタラクティブシェルでコードを実行すると、もちろん、対話シェルの外でスクリプトを実行しても、プログラムはあまりにも早く終了して何が起こるかを知ることができますが、プログラムを開くためにinputへの呼び出しを追加すると正しく動作します(私はpython 3.2.2 on Linux)。Tkinterアプリケーションでmainloopを呼び出す必要はありますか?

それでは、mainloopは正確に何を行いますか、それをいつ呼び出す必要がありますか?

EDIT: は明確にするために、私はGNOMEターミナルを開き、

$python3 
>>> import tkinter 
>>> root = tkinter.Tk() 

ウィンドウがすぐに表示されたメインループを呼び出すことなく、入力して、より複雑なTkinterの機能は、例えば(同様に動作すると思われる場合は、ウィンドウにボタンを追加する)。 IDLEでは、mainloopを呼び出す必要があります。メインループが呼び出されるまで、何も描画しないで、イベントを処理する必要はありません。

答えて

38

あなたの主な質問に対する答えは、アプリケーションを実行する準備ができたら、mainloopを一度だけ呼び出す必要があります。この文脈において

while True: 
    event=wait_for_event() 
    event.process() 
    if main_window_has_been_destroyed(): 
     break 

mainloopはおおよそこの(それらは、法の実際の名前ではなく、名前が単に点を説明するためのものである)ように見える無限ループよりもはるかにはありません「イベント」は、ユーザの操作(マウスクリック、キー押下など)と、ウィジェットを描画または再描画するためのツールキットまたはOS /ウィンドウマネージャからの要求の両方を意味します。そのループが実行されていない場合、イベントは処理されません。イベントが処理されない場合は、画面に何も表示されず、無限ループが実行されていない限り、プログラムは終了する可能性があります。

これを対話的に呼び出す必要はありません。これは便利なことです。それ以外の場合は、mainloopを呼び出すと、コマンドを入力することは不可能です。これは、メインウィンドウが破棄されるまでmainloopが実行されるためです。

7

プログラムを対話型GUIと比較して、100番目のフィボナッチ数を計算するプログラムと比較します。後者のプログラムはすべて一連のステップを順番に、トップからボトムまで順番に実行する必要があります。一連のステップとそのシーケンシングは事前に分かっていて、プログラムを何回実行しても一定のままです。

しかし、GUIプログラムは異なります。任意の時点で、あらゆる種類のさまざまな種類のイベントや対話を処理できる必要があります。この要件は、しばしばイベントループと呼ばれるプログラミング構造を使用して実装されます。イベントループは、プログラムの中央制御構造です。イベントが発生するのを待ってから、適切なハンドラをディスパッチします。

あなたは使用している対話型シェルについて言及していませんでしたが、私はそれがIDLEであると推測しています。 IDLE自体はTkinterプログラムであり、既にイベントループが進行しています。したがって、シェルに入力しているTkinterコードがIDLEのイベントループにバインドされている可能性があります。

+0

申し訳ありませんが、私が言及している必要があります:私は(明らかにCで書かれている)GNOME端末に(アイドルでない)標準のpythonシェルを使用しています。だから私が見る限り、自分のコードを除いて、何もtkinterに影響を与えるものは何もしてはいけません。 – James

+1

IDLEで同じことを試したところ、同じ動作をしません。メインループを呼び出すまではウィンドウが表示されません。 – James

-3

私は、スクリプト内のどこでもmainloopに直接電話をかけているのではなく、atexitの一部として追加することにしました。つまり、Pythonインタプリタがクローズダウンを開始すると判断したら、 Tkのメインループに入る予定。これは、ユーザーが実際に終了するのTkを告げるまで、シャットダウンシーケンスを終了することを防止する(Macのコマンド-Qで、またはWindowsでの赤いXをクリックして、IEを。)

from Tkinter import Tk 
root = Tk() 

import atexit 
atexit.register(root.mainloop) 

にあるようですシステムコマンドラインからmainloopに電話する必要はありません。 Pythonインタプリタは、あなたからのさらなる入力を待っているので(あなたがexit()を実行するまで)、それなしで実行し続けます。

+1

_ "メインループを呼び出すのは、アプリケーションが自動的に" _:を間違った評価で閉じるのを防ぐことだけです。イベントキューを管理します。これは、アプリケーションの終了を防ぐだけではありません。また、あなたは自分がやっていると思っていることさえしていません。実際には、終了時ではなく即座に 'mainloop()'を呼び出しています。 –

+1

@BryanOakley - うわー、私は 'mainloop()'へのその偶発的な呼び出しを修正しました。とにかく、あなたは間違っていると思います。あなたの答えでは、対話型インタラクティブでmainloopを呼び出す必要がないということは、 "単なる利便性"であるということです。どう?便利なことなら、インタラクティブなインタプリタか 'Tkinter'モジュールのどちらかにこれを可能にする特別なコードが含まれていなければなりません。私はそのコードが存在するとは思わない。それが言う文書もありません。あなたが言うようにメインループが魔法であることを証明するのはあなたの負担です。 – ArtOfWarfare

+0

私はatexitについて聞いたことがないので、私はunittest中に手動でアプリケーションを閉じることなく 'Tk()'アプリケーションを呼び出すことができるので、この答えが見つかったことを嬉しく思っています。 –

-3

次のように:

from tkinter import * 

tk = Tk() 
canvas = Canvas(tk, width=500, height=500) 
canvas.pack() 
canvas.create_line(0, 0, 500, 500) 

mainloop() 
関連する問題