タートルグラフィックがすぐ消える?exitonclick()で解決!

2025-06-06

この関数は、turtle グラフィックウィンドウをクリックするまでプログラムの実行を一時停止させる役割を果たします。つまり、プログラムが全ての描画処理を終えた後でも、ウィンドウがすぐに閉じてしまうのを防ぎます。

ユーザーがウィンドウをクリックすると、この関数はプログラムの実行を再開し、通常はプログラムが終了します。

主な用途:

  • ウィンドウの保持
    プログラムが終了しても、描画ウィンドウを閉じずに表示し続けるため。
  • 描画結果の確認
    プログラムが描画した図形やアニメーションをユーザーがじっくりと確認できるようにするため。
import turtle

# タートルグラフィックのセットアップ
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.bgcolor("lightblue")

pen = turtle.Turtle()
pen.speed(1) # 描画速度

# 四角形を描く
for _ in range(4):
    pen.forward(100)
    pen.right(90)

# ウィンドウがクリックされるまで待機
turtle.exitonclick()


turtle.exitonclick() は非常に便利な関数ですが、使い方によっては予期せぬ挙動やエラーが発生することがあります。

NameError: name 'turtle' is not defined または NameError: name 'exitonclick' is not defined

これは、turtle モジュールが適切にインポートされていない場合に発生するエラーです。

  • トラブルシューティング

    • プログラムの冒頭で必ず import turtle を記述してください。
    • もし from turtle import * のようにインポートしている場合は、exitonclick() を直接呼び出すことができます。しかし、一般的には import turtle を行い、turtle.exitonclick() のように接頭辞を付ける方が推奨されます。

    良い例

    import turtle
    # ...
    turtle.exitonclick()
    

    (注意が必要な例)

    from turtle import * # この場合、turtle. は不要
    # ...
    exitonclick()
    
  • 原因
    import turtle が行われていないか、異なる方法でインポートされている(例:from turtle import * のみで turtle. を付けていない)可能性があります。

ウィンドウがすぐに閉じてしまう / exitonclick() が機能しない

これは、turtle.exitonclick() がプログラムの適切な場所で呼び出されていないか、プログラムがその呼び出しに到達する前に終了してしまっている場合に発生します。

  • トラブルシューティング

    • 必ずプログラムの全ての描画処理が終わった最後の行に turtle.exitonclick() を配置してください。
    • turtle.exitonclick() の直前の行でエラーが発生していないか確認してください。エラーが発生している場合、そのエラーを解決しない限り exitonclick() は実行されません。
    • もしインタラクティブシェルで実行していて問題が発生する場合は、一度スクリプトファイル(.py)として保存し、コマンドラインから実行してみてください。


    import turtle
    
    # 描画処理
    # ...
    
    # 描画が終わった後に呼び出す
    turtle.exitonclick()
    
  • 原因

    • turtle.exitonclick() がプログラムの最後に配置されていない。
    • turtle.exitonclick() の前にエラーが発生し、プログラムがそこで停止している。
    • インタラクティブシェル(例:Jupyter NotebookやIDLE)で実行している場合、挙動がデスクトップアプリケーションと異なることがある。

複数のタートルウィンドウが生成される / 予期せぬウィンドウの挙動

これは、turtle.Screen() を複数回呼び出したり、スクリーンオブジェクトを適切に扱っていない場合に起こり得ます。

  • トラブルシューティング
    • 通常、turtle.Screen() はプログラム内で一度だけ呼び出すべきです。
    • もし複数の描画が必要な場合でも、単一のスクリーンオブジェクトを使用し、必要に応じてタートルオブジェクトをリセット(turtle.clear()turtle.reset())してください。
    • turtle.done() という関数もありますが、これは exitonclick() と同じような役割を持ちます。しかし、両方を同時に使うと意図しない挙動になることがあるので、どちらか一つを選んで使用してください。exitonclick() の方がクリックでの終了に特化しており、より直感的です。
  • 原因
    • turtle.Screen() を複数回呼び出して、複数の描画ウィンドウを作成している。
    • タートルオブジェクトを適切にリセットまたはクリアしていない。

プログラムが応答しなくなる / フリーズする

これは稀ですが、無限ループや非常に時間のかかる計算が exitonclick() の前にあり、UIイベントループがブロックされてしまう場合に発生する可能性があります。

  • トラブルシューティング
    • プログラムのロジックを確認し、exitonclick() が呼ばれる前に無限ループに入っていないか確認してください。
    • 複雑な計算を行う場合は、それがバックグラウンドで実行されるように工夫するか、計算の完了を待ってから exitonclick() を呼び出すようにしてください。
  • 原因
    • exitonclick() が呼び出される前に、無限ループや非常に重い計算が実行されている。
    • UIイベント処理がブロックされている。

環境依存の問題(特にウェブベースの環境や古い環境)

特定の環境(例:オンラインのPython実行環境、古いバージョンのPythonやtkinter)では、turtle モジュールの描画やイベント処理が意図通りに機能しないことがあります。

  • トラブルシューティング
    • できれば、ローカルのPCにPythonをインストールし、IDLEやVS Codeなどの開発環境で実行してみてください。
    • Pythonのバージョンを最新にアップデートしてみてください。
    • もしオンライン環境での実行にこだわる場合は、その環境のドキュメントを確認し、turtle モジュールのサポート状況を調べてください。一部のオンライン環境では、turtle のGUI機能が制限されている場合があります。
  • 原因
    • オンラインの実行環境が tkinterturtle が依存するGUIライブラリ)をサポートしていない。
    • Pythonのバージョンが古い。
    • OSやGUIライブラリの設定問題。


turtle.exitonclick() の最も基本的な目的は、タートルグラフィックのウィンドウが、ユーザーがクリックするまで閉じないようにすることです。これにより、描画された結果をじっくりと確認できます。

基本的な使用例:シンプルな図形を描いてウィンドウを保持する

これは、exitonclick() の最も一般的な使い方です。

import turtle

# 1. スクリーンオブジェクトの作成 (描画するキャンバス)
screen = turtle.Screen()
screen.setup(width=600, height=400) # ウィンドウのサイズを設定
screen.bgcolor("lightgreen")       # 背景色を設定
screen.title("My First Turtle Drawing") # ウィンドウのタイトルを設定

# 2. タートルオブジェクトの作成 (描画するペン)
pen = turtle.Turtle()
pen.shape("turtle") # タートルの形を「亀」にする
pen.color("blue")   # ペンの色を青にする
pen.pensize(3)      # ペンの太さを3にする
pen.speed(1)        # 描画速度 (1=遅い, 10=速い, 0=最速)

# 3. 図形の描画 (正方形)
for _ in range(4):
    pen.forward(100) # 100ピクセル前進
    pen.right(90)    # 右に90度回転

# 4. ウィンドウがクリックされるまで待機
# この行が非常に重要です。これがなければ、描画後すぐにウィンドウが閉じます。
turtle.exitonclick()

解説

  • turtle.exitonclick(): この関数が呼び出されると、ウィンドウはユーザーがどこかをクリックするまで開いたままになります。 クリックすると、プログラムの実行が再開され、通常はそこで終了します。
  • for _ in range(4): ...: ループを使って正方形を描画します。
  • pen = turtle.Turtle(): 実際に描画を行う「タートル」(ペン)を作成します。複数のタートルを作成することも可能です。
  • screen = turtle.Screen(): 描画領域となるウィンドウ(スクリーン)を作成します。通常、これ1つで十分です。
  • import turtle: turtle モジュールをインポートします。

複数のタートルを使用し、それぞれの描画後にウィンドウを保持する

exitonclick() は、複数のタートルオブジェクトが存在しても、単一のスクリーンオブジェクト(ウィンドウ)に対して機能します。

import turtle

screen = turtle.Screen()
screen.setup(width=700, height=500)
screen.bgcolor("lightyellow")
screen.title("Multiple Turtles")

# 最初のタートル
turt1 = turtle.Turtle()
turt1.color("red")
turt1.pensize(2)
turt1.penup() # ペンを上げる(描画しない)
turt1.goto(-150, 0) # 位置を移動
turt1.pendown() # ペンを下ろす(描画開始)
turt1.speed(3)
for _ in range(3): # 三角形を描く
    turt1.forward(100)
    turt1.left(120)

# 2番目のタートル
turt2 = turtle.Turtle()
turt2.color("green")
turt2.pensize(2)
turt2.penup()
turt2.goto(50, 0)
turt2.pendown()
turt2.speed(3)
for _ in range(5): # 五角形を描く
    turt2.forward(80)
    turt2.right(72)

# 両方のタートルが描画を終えた後、ウィンドウを保持
turtle.exitonclick()

解説

  • turtle.exitonclick() は、両方のタートルが描画を完了した後で一度だけ呼び出されます。これにより、両方の図形が表示された状態でウィンドウが保持されます。
  • turt1turt2 という2つの異なるタートルオブジェクトを作成し、それぞれ異なる図形を描いています。

関数内でタートルグラフィックを使用し、最後にウィンドウを保持する

プログラムが複数の関数に分かれている場合でも、exitonclick() はメインの実行フローの最後に配置します。

import turtle

def draw_square(t, size, color):
    """正方形を描画する関数"""
    t.color(color)
    t.pensize(2)
    for _ in range(4):
        t.forward(size)
        t.right(90)

def draw_star(t, size, color):
    """星形を描画する関数"""
    t.color(color)
    t.pensize(3)
    t.penup()
    t.goto(-100, 100) # 星の開始位置
    t.pendown()
    for _ in range(5):
        t.forward(size)
        t.right(144)

# メインの実行部分
if __name__ == "__main__":
    screen = turtle.Screen()
    screen.setup(width=600, height=600)
    screen.bgcolor("white")
    screen.title("Drawing with Functions")

    my_turtle = turtle.Turtle()
    my_turtle.speed(5)

    draw_square(my_turtle, 150, "purple")

    my_turtle.penup()
    my_turtle.goto(50, -50) # 位置を移動
    my_turtle.pendown()

    draw_star(my_turtle, 100, "orange")

    # 全ての描画が完了したら、ウィンドウを保持
    turtle.exitonclick()

解説

  • 最終的に、turtle.exitonclick() が呼び出され、描画結果が表示されたままになります。
  • メインの実行ブロック (if __name__ == "__main__":) でタートルオブジェクトを作成し、これらの関数を呼び出して描画を行います。
  • draw_squaredraw_star という2つの関数を定義しています。

exitonclick() を使用しない場合との比較 (BAD PRACTICE!)

exitonclick() を使用しない場合、プログラムは描画が完了するとすぐに終了し、ウィンドウが閉じます。これでは、描画結果をほとんど見ることができません。

import turtle

screen = turtle.Screen()
screen.setup(width=400, height=300)
screen.bgcolor("lightgray")
screen.title("Will Close Immediately!")

pen = turtle.Turtle()
pen.speed(0) # 最速で描画

pen.circle(50) # 円を描く

# ここに turtle.exitonclick() がないため、
# 描画後、プログラムはすぐに終了し、ウィンドウが閉じる
# ほとんど何も見えない!
  • このコードを実行すると、円が描画されますが、すぐにウィンドウが閉じてしまい、描画結果を確認する時間がほとんどありません。 これが turtle.exitonclick() が必要な理由です。


turtle.done()

turtle.done()turtle.exitonclick() と非常によく似た役割を持ちます。違いは、turtle.done()クリックを待つのではなく、単にタートルグラフィックのイベントループを開始し、プログラムの終了を阻止する点です。つまり、ユーザーがウィンドウを閉じるボタン(Xボタンなど)をクリックするまでウィンドウを開いたままにします。

  • 使用例

    import turtle
    
    screen = turtle.Screen()
    screen.setup(width=600, height=400)
    screen.bgcolor("pink")
    
    pen = turtle.Turtle()
    pen.speed(1)
    
    pen.forward(100)
    pen.left(90)
    pen.forward(100)
    
    # ウィンドウが閉じられるまでプログラムを保持
    turtle.done()
    
  • 欠点

    • 特にありませんが、クリックイベントを待つ必要がない場合に選択します。
    • exitonclick() と同じく、描画後にウィンドウがすぐに閉じるのを防ぎます。
    • クリックを待つ必要がないため、プログラムがクリックイベントに依存しない場合に適しています。

input() を使用してユーザーからの入力を待つ

これは、タートルグラフィックとは直接関係なく、Pythonの標準的な入力関数を使用してプログラムの実行を一時停止する方法です。ユーザーがEnterキーを押すまで待機します。

  • 使用例

    import turtle
    
    screen = turtle.Screen()
    screen.setup(width=600, height=400)
    screen.bgcolor("lightgray")
    
    pen = turtle.Turtle()
    pen.circle(50)
    
    # ユーザーがターミナルでEnterキーを押すまで待機
    input("Press Enter to close the window...")
    # ウィンドウを閉じる(オプション)
    turtle.bye() # または screen.bye()
    

    注意
    input() の後に turtle.bye() または screen.bye() を使用しないと、入力後もウィンドウが閉じずに残ってしまうことがあります。

  • 欠点

    • タートルグラフィックウィンドウ自体がクリックイベントに反応するわけではありません。ユーザーはターミナル(コンソール)に戻ってEnterキーを押す必要があります。
    • グラフィカルな操作ではありません。
  • 利点

    • turtle モジュールに依存しないため、Pythonの基本的な知識で理解できます。
    • コマンドラインでプロンプトを表示し、ユーザーに明確な操作を促すことができます。

time.sleep() を使用して一定時間ウィンドウを表示する

これは、プログラムの実行を一定時間だけ一時停止させる方法です。

  • 使用例

    import turtle
    import time # timeモジュールをインポート
    
    screen = turtle.Screen()
    screen.setup(width=600, height=400)
    screen.bgcolor("lightgreen")
    
    pen = turtle.Turtle()
    pen.dot(100, "red") # 大きな赤い点を描く
    
    # 5秒間ウィンドウを表示し、その後閉じる
    time.sleep(5) # 5秒間待機
    
    # ウィンドウを閉じる
    turtle.bye() # または screen.bye()
    

    注意
    time.sleep() を使用した後、明示的に turtle.bye()screen.bye() を呼び出してウィンドウを閉じるのが一般的です。これを行わないと、Pythonスクリプトは終了してもウィンドウがOS上に残ってしまう場合があります。

  • 欠点

    • 指定した時間が経過すると、ユーザーの操作に関わらずウィンドウが閉じてしまいます。
    • ユーザーがじっくり見たい場合や、操作してから閉じたい場合には不向きです。
  • 利点

    • 単純で実装が容易です。
    • デモンストレーションなどで、短い時間だけ結果を見せたい場合に便利です。

GUIライブラリのイベントループ(より高度な方法)

turtle モジュールは内部的に tkinter というGUIライブラリを使用しています。より複雑なインタラクティブなアプリケーションを作成する場合、直接 tkinter のイベントループを制御する方法も考えられます。これは turtle の範疇を超えますが、代替手段として概念的に理解しておくと良いでしょう。

  • 使用例 (概念的なもの)

    # import tkinter as tk
    # root = tk.Tk()
    # canvas = tk.Canvas(root, width=600, height=400)
    # canvas.pack()
    # # ここでtkinterを使って描画やイベントハンドリングを設定
    # root.mainloop() # Tkinterのイベントループを開始
    

    turtle.done()turtle.exitonclick() は、この tkinter.mainloop() のようなイベントループを、turtle モジュールが提供する形で簡単に開始するものです。

  • 欠点

    • turtle モジュールの手軽さが失われ、コードが複雑になります。
    • tkinter の知識が必要です。
  • 利点

    • より細かなGUI制御が可能になります。
    • ボタンやテキストボックスなどのウィジェットを追加できます。
  • 簡単な一時停止
    input() または time.sleep()
    • デバッグや一時的な表示確認には便利ですが、本格的な用途には向きません。
  • 最も推奨される代替方法
    turtle.done()
    • exitonclick() と同じく、ウィンドウを保持し、ユーザーが手動で閉じるまで表示し続けます。クリックを待つ必要がない点が異なります。