Methods of TurtleScreen/Screen and corresponding functions (turtle)

2025-06-06

turtleモジュールは、グラフィカルな描画を簡単に行うためのPythonの標準ライブラリです。カメ(タートル)が画面上を移動しながら線を描く様子をシミュレートします。このモジュールには、描画を行う「カメ」と、そのカメが活動する「画面」という2つの主要な要素があります。

ここで説明するのは、後者の「画面」を制御するTurtleScreen(またはそのエイリアスであるScreen)クラスのメソッドと、それらに対応するモジュールレベルの関数です。これらのメソッドや関数は、画面のセットアップ、イベント処理、アニメーション制御など、描画環境全体を管理するために使用されます。

TurtleScreen/Screen とは?

TurtleScreenクラスは、タートルが描画を行うウィンドウまたはキャンバスを表します。このクラスのインスタンスを通じて、描画領域のサイズ、背景色、イベント(クリック、キー入力など)の処理、アニメーション速度の制御など、画面全体の振る舞いを設定できます。

通常、Screenオブジェクトは以下のように作成します。

import turtle
screen = turtle.Screen()

多くのTurtleScreenメソッドには、モジュールレベルの対応する関数が存在します。これは、簡単に画面を設定できるようにするためです。例えば、screen.bgcolor("blue")turtle.bgcolor("blue")は同じ効果を持ちます。

主要なメソッドと対応する関数

画面の制御と設定
  • title(titlestring)

    • 説明
      描画ウィンドウのタイトルバーに表示される文字列を設定します。
    • 対応する関数
      turtle.title()

    • screen.title("私のタートルグラフィックス") # ウィンドウタイトルを設定
      
  • bgpic(picname=None)

    • 説明
      描画ウィンドウの背景画像を設定します。GIF形式の画像ファイルがサポートされています。Noneを指定すると背景画像が削除されます。
    • 対応する関数
      turtle.bgpic()

    • screen.bgpic("background.gif") # "background.gif"を背景画像として設定
      
  • bgcolor(*args)

    • 説明
      描画ウィンドウの背景色を設定します。色の名前("red"など)またはRGB値で指定できます。
    • 対応する関数
      turtle.bgcolor()

    • screen.bgcolor("skyblue") # 背景色をスカイブルーに設定
      # または
      # turtle.bgcolor("skyblue")
      
  • screensize(canvwidth=None, canvheight=None, bg=None)

    • 説明
      タートルが移動できる描画領域(キャンバス)のサイズを設定します。ウィンドウサイズと異なり、キャンバスはウィンドウよりも大きくすることができます(スクロールバーが表示されます)。背景色も設定できます。
    • 対応する関数
      turtle.screensize()

    • screen.screensize(canvwidth=1000, canvheight=800, bg="lightgray") # キャンバスサイズを1000x800、背景色を薄い灰色に設定
      
    • 説明
      描画ウィンドウのサイズと開始位置を設定します。
    • width, height: ウィンドウの幅と高さをピクセル単位(または比率)で指定します。
    • startx, starty: ウィンドウの左上隅のX座標とY座標を設定します。Noneの場合、画面中央に配置されます。
    • 対応する関数
      turtle.setup()

    • screen.setup(width=600, height=400, startx=0, starty=0) # ウィンドウサイズを600x400、左上を(0,0)に設定
      # または
      # turtle.setup(width=600, height=400, startx=0, starty=0)
      
アニメーションと更新
  • mainloop() / done()

    • 説明
      turtleグラフィックスアプリケーションをイベントループに入らせ、ウィンドウが開いたままになるようにします。ユーザーがウィンドウを閉じるまでプログラムが終了しないようにするために、スクリプトの最後に呼び出す必要があります。done()mainloop()のエイリアスです。
    • 対応する関数
      turtle.mainloop(), turtle.done()

    • # 描画処理...
      screen.mainloop() # ウィンドウが開いたままになるようにする
      
  • delay(delay=None)

    • 説明
      アニメーションの更新間隔(ミリ秒)を設定します。tracer()delay引数と同じです。
    • 対応する関数
      turtle.delay()

    • screen.delay(10) # 各描画ステップ間で10ミリ秒の遅延を設定
      
  • update()

    • 説明
      tracer(0)でアニメーションをオフにした際に、手動で画面を更新します。
    • 対応する関数
      turtle.update()

    • screen.tracer(0)
      # 多数の描画コマンド
      screen.update() # ここで一度に描画を反映
      
  • tracer(n=None, delay=None)

    • 説明
      アニメーションのオン/オフを切り替え、描画更新の頻度を制御します。n0の場合、アニメーションはオフになり、描画は即座に行われます(高速描画)。n1以上の場合、n回移動するごとに画面が更新されます。delayは更新間の遅延時間(ミリ秒)です。
    • 対応する関数
      turtle.tracer()

    • screen.tracer(0) # アニメーションをオフにし、高速描画
      # 描画処理...
      screen.update() # 描画後に手動で画面を更新
      # または
      # turtle.tracer(0)
      
イベント処理
  • ontimer(fun, t=0)

    • 説明
      tミリ秒後に一度だけfunを呼び出すようにタイマーを設定します。定期的に実行するには、funの内部で自分自身を再度スケジュールします。
    • 対応する関数
      turtle.ontimer()

    • def animate():
          my_turtle.forward(1)
          screen.ontimer(animate, 10) # 10ミリ秒後に再度animateを呼び出す
      
      animate() # アニメーション開始
      
  • listen()

    • 説明
      キーイベントをリッスン(監視)するよう画面に指示します。onkeyを使用する前に必ず呼び出す必要があります。
    • 対応する関数
      turtle.listen()

    • screen.onkey(move_forward, "Up")
      screen.listen() # キーイベントを有効にする
      
  • onkey(fun, key)

    • 説明
      指定されたキーが押されたときに呼び出される関数を設定します。
    • 対応する関数
      turtle.onkey()

    • def move_forward():
          my_turtle.forward(50)
      
      screen.onkey(move_forward, "Up") # 上矢印キーが押されたらmove_forwardを呼び出す
      
  • onclick(fun, btn=1, add=None)

    • 説明
      画面がクリックされたときに呼び出される関数を設定します。funは呼び出す関数、btnはマウスのボタン(1:左、2:中央、3:右)を指定します。
    • 対応する関数
      turtle.onclick()

    • def handle_click(x, y):
          print(f"画面がクリックされました: ({x}, {y})")
      
      screen.onclick(handle_click) # 画面クリック時にhandle_clickを呼び出す
      
  • colormode(cmode=None)

    • 説明
      色のモードを設定します。1.0(RGB値が0.0から1.0の範囲)または255(RGB値が0から255の範囲)を指定します。
    • 対応する関数
      turtle.colormode()

    • screen.colormode(255) # RGB値を0-255の範囲で指定できるようにする
      
  • mode(mode=None)

    • 説明
      スクリーン座標系のモードを設定します。"standard"(デフォルト、右方向が0度、反時計回りが正)、"logo"(上方向が0度、時計回りが正)、"world"(カスタム座標系)があります。
    • 対応する関数
      turtle.mode()

    • screen.mode("logo") # 座標系をLogoモードに設定
      
  • clearscreen() / clear()

    • 説明
      画面上のすべての描画をクリアしますが、背景色などの設定は保持します。clear()clearscreen()のエイリアスです。
    • 対応する関数
      turtle.clearscreen(), turtle.clear()

    • screen.clearscreen() # 描画のみクリア
      
  • reset()

    • 説明
      画面上のすべての描画をクリアし、設定をデフォルト状態に戻します。
    • 対応する関数
      turtle.reset()

    • screen.reset() # 画面をリセット
      
  • exitonclick()

    • 説明
      画面がクリックされたときに、タートルグラフィックスを終了します。screen.onclick(bye)screen.mainloop()の組み合わせに似ています。
    • 対応する関数
      turtle.exitonclick()

    • # 描画処理...
      screen.exitonclick() # クリックで終了
      

なぜメソッドと関数の両方があるのか?

turtleモジュールが提供するモジュールレベルの関数(例: turtle.bgcolor()) は、内部的にデフォルトのScreenインスタンスに対して対応するメソッド(例: turtle.Screen().bgcolor()) を呼び出しています。

これは、初心者が簡単にturtleグラフィックスを始められるようにするためです。通常、最初にscreen = turtle.Screen()といったコードを書かなくても、turtle.forward(100)turtle.bgcolor("red")のように直接モジュールレベルの関数を呼び出すことができます。

しかし、複数のタートルオブジェクトを扱う場合や、より細かく画面の振る舞いを制御したい場合には、明示的にScreenオブジェクトを作成し、そのメソッドを呼び出す方が推奨されます。

  • Screenオブジェクトのメソッド
    複数のタートルや複雑な描画環境を扱う場合に、より明確で制御しやすいコードを書くことができます。
  • モジュールレベルの関数
    簡単なスクリプトや手軽に試したい場合に便利です。暗黙的にデフォルトの画面インスタンスを操作します。


turtleモジュールは視覚的で楽しくプログラミングを学べるツールですが、特に初めて使う際にはいくつかの一般的な落とし穴があります。ここでは、Screenオブジェクトや関連する関数に起因するエラーとその解決策を見ていきましょう。

ウィンドウが表示されない、またはすぐに閉じてしまう

これは最もよくある問題です。プログラムが終了すると、turtleウィンドウも同時に閉じられてしまいます。

  • 解決策
    プログラムの最後にscreen.mainloop()またはturtle.done()を呼び出します。これにより、turtleウィンドウはユーザーが手動で閉じるまで開いたままになります。

    import turtle
    
    screen = turtle.Screen()
    t = turtle.Turtle()
    
    t.forward(100)
    t.left(90)
    t.forward(100)
    
    # これが重要!ウィンドウを開いたままにする
    screen.mainloop()
    # または turtle.done()
    

    Jupyter NotebookやIDLEなどのインタラクティブな環境では、mainloop()が不要な場合がありますが、通常のPythonスクリプトとして実行する場合は必須です。

  • 原因
    turtleグラフィックスは、イベントループが実行されている間のみウィンドウを開いたままにすることができます。プログラムの描画処理が完了すると、明示的にイベントループを開始しない限り、プログラムは終了し、ウィンドウも閉じられます。

    • プログラムを実行しても、turtleウィンドウが全く表示されない。
    • 一瞬だけウィンドウが表示されてすぐに消える。
    • コマンドラインで実行した場合、「Process finished with exit code 0」などのメッセージが表示されるが、ウィンドウは開かない。

イベントハンドラが機能しない (onkey, onclick など)

キー入力やマウスクリックに応答しない場合。

  • 解決策

    1. screen.listen()を呼び出す
      イベントハンドラを設定した後、必ずscreen.listen()を呼び出してください。

      import turtle
      
      screen = turtle.Screen()
      t = turtle.Turtle()
      
      def move_forward():
          t.forward(20)
      
      screen.onkey(move_forward, "Up") # 関数名を渡す (呼び出しではない)
      screen.listen() # これを忘れない!
      
      screen.mainloop()
      
    2. 関数の参照を渡す
      onkey()onclick()に渡すのは関数名(関数のオブジェクトそのもの)であり、その関数の実行結果ではありません。

      誤った例
      screen.onkey(my_function(), "space") 正しい例: screen.onkey(my_function, "space")

    3. mainloop()を使用する
      イベント駆動型プログラミングでは、turtle.mainloop()がプログラムの制御をイベントシステムに渡し、イベントが発生するたびに関連する関数を呼び出します。自分で無限ループを実装すると、このイベント処理が妨げられる可能性があります。

  • 原因

    1. screen.listen()の呼び忘れ
      Screenオブジェクトにイベントをリッスンするよう指示していないため、キー入力やマウスクリックを検出できません。
    2. 関数呼び出しのエラー
      onkey(my_function(), "key")のように、関数自体を呼び出してその結果を渡している場合。イベントハンドラには関数の「参照」を渡す必要があります。
    3. 無限ループとの競合
      while True:のような自前の無限ループをmainloop()の代わりに使っている場合、turtleのイベントループが実行されず、イベントが処理されません。
  • エラーの兆候

    • onkey()onclick()で設定した関数が呼び出されない。
    • キーを押してもタートルが動かない、画面が反応しない。

tkinter.TclError: cannot use geometry manager inside .

Screen()を複数回呼び出そうとしたときに発生することがあります。

  • 解決策
    プログラム全体でScreenオブジェクトのインスタンスを1つだけ作成し、それを使い回すようにします。

    import turtle
    
    # 最初にScreenオブジェクトを作成し、以降はこれを使用する
    screen = turtle.Screen()
    # screen2 = turtle.Screen() # これは通常避けるべき!
    
    t1 = turtle.Turtle()
    t2 = turtle.Turtle()
    
    # 描画処理...
    
    screen.mainloop()
    

    もし本当に複数の独立したウィンドウが必要な場合は、tkinterを直接使用して複数のウィンドウを作成し、それぞれのウィンドウ内にturtle.RawTurtleturtle.TurtleScreenを紐づけるという、より高度なテクニックが必要になります。これは通常のturtleの範囲を超えます。

  • 原因
    turtle.Screen()は、背後でTkinterのルートウィンドウを初期化します。Tkinterのルートウィンドウは通常、アプリケーションごとに1つしか作成できません。したがって、turtle.Screen()も1つのプログラム内で1回だけ呼び出すべきです。

  • エラーの兆候

    • tkinter.TclError: cannot use geometry manager inside .
    • _Screenオブジェクトの初期化に関するエラーメッセージ。

アニメーションが遅い、または速すぎる

描画速度の調整に関する問題。

  • 解決策

    • 高速化 (アニメーションをオフにする)
      screen.tracer(0)を呼び出すと、すべての描画操作が画面に即座に反映されなくなり、非常に高速に処理されます。描画が終わった後にscreen.update()を呼び出すことで、一度に画面を更新します。

      import turtle
      
      screen = turtle.Screen()
      t = turtle.Turtle()
      
      screen.tracer(0) # アニメーションをオフ
      
      for i in range(360):
          t.forward(1)
          t.left(1)
      
      screen.update() # すべての描画を一度に表示
      screen.mainloop()
      
    • 速度調整 (アニメーションの頻度と遅延)
      screen.tracer(n)nを大きくすると、n回のステップごとに画面が更新されます。screen.delay(t)は各更新間の遅延時間をミリ秒で設定します。

      import turtle
      
      screen = turtle.Screen()
      t = turtle.Turtle()
      
      screen.tracer(2)  # 2ステップごとに更新
      screen.delay(10) # 各更新間に10ミリ秒の遅延
      
      for i in range(360):
          t.forward(1)
          t.left(1)
      
      screen.mainloop()
      
  • 原因

    • 遅い場合
      tracer()の引数nが大きく、delayも大きい、またはデフォルトの設定が遅い環境。
    • 速い場合
      tracer(0)を設定し、update()を呼び出していない。または、非常に単純な描画処理を高速で何度も繰り返している。
  • エラーの兆候

    • 描画が非常に遅い、カメの動きがカクカクする。
    • 描画が一瞬で終わってしまい、何が描かれたか分からない。

画像が読み込まれない (bgpic)

背景画像が期待通りに表示されない。

  • 解決策

    1. ファイルパスの確認

      • 画像ファイルがスクリプトと同じディレクトリにあるか確認してください。
      • 別のディレクトリにある場合は、絶対パスまたは相対パスを正しく指定してください。
      • ファイル名に誤字がないか確認してください。
    2. 画像形式の確認

      • 使用している画像がGIF形式であることを確認してください。必要であれば、画像編集ソフトでGIFに変換してください。
      import turtle
      
      screen = turtle.Screen()
      # カレントディレクトリに "my_background.gif" があると仮定
      screen.bgpic("my_background.gif")
      
      t = turtle.Turtle()
      t.hideturtle() # タートルを非表示にする(背景画像と重ならないように)
      
      screen.mainloop()
      
  • 原因

    1. ファイルパスの誤り
      画像ファイルが存在しない、または指定されたパスが間違っている。
    2. サポートされていない画像形式
      turtleモジュールは主にGIF形式の画像をサポートしています。PNGやJPGなどの他の形式は直接サポートしていません(TkinterのImageTkモジュールを使えば可能ですが、turtle標準の範囲外です)。
  • エラーの兆候

    • bgpic()で指定した画像が表示されない。
    • エラーメッセージが表示される(ファイルが見つからない、形式がサポートされていないなど)。

座標系の理解不足 (mode, colormode)

タートルの動きや色が期待と異なる。

  • 解決策

    • modeの確認
      どの座標系を使用しているか意識し、必要に応じてscreen.mode("standard")またはscreen.mode("logo")で明示的に設定します。

      import turtle
      
      screen = turtle.Screen()
      t = turtle.Turtle()
      
      # デフォルトは "standard" (右が0度、反時計回りが正)
      t.forward(100)
      t.left(90) # 上を向く
      
      # Logoモード (上が0度、時計回りが正)
      screen.mode("logo")
      t.penup()
      t.goto(-50, -50)
      t.pendown()
      t.setheading(0) # Logoモードでは上を向く
      t.left(90) # Logoモードでは右を向く
      t.forward(100)
      
      screen.mainloop()
      
    • colormodeの確認
      RGB値を0から255の範囲で指定したい場合は、必ずscreen.colormode(255)を呼び出してください。

      import turtle
      
      screen = turtle.Screen()
      screen.colormode(255) # RGB値を0-255で指定可能にする
      
      t = turtle.Turtle()
      t.color((255, 0, 0)) # 赤色
      t.forward(50)
      t.color(0, 255, 0) # 緑色
      t.forward(50)
      
      screen.mainloop()
      
  • 原因

    • mode
      デフォルトの"standard"モードでは、右方向が0度で反時計回りが正の角度です。これに対し、"logo"モードでは上方向が0度で時計回りが正の角度になります。これを混同すると、タートルの向きが変わります。
    • colormode
      デフォルトではRGB値は0.0から1.0の範囲で指定します。colormode(255)を呼び出すまで、0から255の整数値で指定することはできません。
  • エラーの兆候

    • left(90)で右に曲がるなど、タートルの方向が意図しない。
    • color((255, 0, 0))と指定しても色が赤にならない。

ウィンドウが「応答なし」になる

特に複雑な描画や無限ループを使用している場合に発生します。

  • 解決策

    1. tracer(0)とupdate()を使用する
      大量の描画を行う場合、tracer(0)でアニメーションをオフにし、すべての描画が終わってからupdate()で一括表示することで、処理を高速化し、応答なしになるのを防ぎます。

    2. ontimer()でタスクを分割する
      時間のかかる処理や連続的なアニメーションは、screen.ontimer()を使って小さなタスクに分割し、定期的に実行するようにします。これにより、各タスクの間にGUIのイベントループが実行される時間が確保され、ウィンドウが応答性を保ちます。

      import turtle
      
      screen = turtle.Screen()
      t = turtle.Turtle()
      t.speed(0) # 最速で描画
      
      angle = 0
      def draw_spiral():
          global angle
          if angle < 360 * 5: # 5回転分描画
              t.forward(2)
              t.left(1)
              angle += 1
              screen.ontimer(draw_spiral, 10) # 10ミリ秒後に再度呼び出す
          else:
              print("描画完了")
      
      draw_spiral() # 最初の描画を開始
      screen.mainloop()
      
    3. 無限ループを避ける
      turtleのメインループはscreen.mainloop()に任せ、自作の無限ループでGUIをブロックしないように注意してください。

  • 原因

    • 重い計算や描画処理
      mainloop()が実行されている間に、非常に時間のかかる計算や描画処理を直接イベントハンドラ内で行うと、GUIのイベントループがブロックされ、ウィンドウが応答しなくなります。
    • 無限ループ
      while True:のような無限ループをmainloop()の「前」に置いて、イベント処理を妨げている場合。
  • エラーの兆候

    • turtleウィンドウがフリーズし、「応答なし」と表示される。
    • プログラムを強制終了するしかない。


turtleモジュールを使用する際、まずScreenオブジェクト(またはモジュールレベルの関数)を使って描画環境を準備します。その後にTurtleオブジェクトを使って絵を描いていきます。

基本的な画面のセットアップと背景色変更

この例では、ウィンドウのサイズを設定し、背景色を変更します。

import turtle

# 1. Screenオブジェクトを作成する
screen = turtle.Screen()

# 2. ウィンドウのタイトルを設定する
screen.title("シンプルなタートルグラフィックス")

# 3. ウィンドウのサイズを設定する (幅600ピクセル、高さ400ピクセル)
# screen.setup()メソッドは、ウィンドウの物理的なサイズを設定します。
screen.setup(width=600, height=400)

# 4. 背景色を設定する
# screen.bgcolor()メソッド、またはturtle.bgcolor()関数が使えます。
screen.bgcolor("lightblue") # 水色の背景

# タートルオブジェクトを作成(描画のためのペン)
t = turtle.Turtle()
t.pensize(3)
t.forward(100)
t.left(90)
t.forward(100)

# 5. ウィンドウが開いたままになるようにイベントループを開始する
# これがないと、プログラムがすぐに終了し、ウィンドウが消えてしまいます。
screen.mainloop()

解説

  • screen.mainloop(): turtleグラフィックスアプリケーションのイベントループを開始します。これにより、ウィンドウはユーザーが閉じるまで開いたままになります。
  • screen.bgcolor(...): ウィンドウの背景色を設定します。色の名前(文字列)またはRGB値のタプルで指定できます。
  • screen.setup(width, height): 描画ウィンドウの幅と高さをピクセル単位で指定します。
  • screen.title(...): ウィンドウのタイトルバーに表示されるテキストを設定します。
  • screen = turtle.Screen(): 描画を行うための「画面」オブジェクトを作成します。
  • import turtle: turtleモジュールをインポートします。

アニメーションの制御 (tracer と update)

複雑な描画を高速に行う場合や、アニメーションの速度を細かく制御したい場合に有用です。

import turtle

screen = turtle.Screen()
screen.title("高速描画とアニメーション")
screen.setup(width=600, height=600)
t = turtle.Turtle()
t.speed(0) # タートルの描画速度を最速に設定(0-10、0が最速)

# 1. アニメーションを一時的にオフにする
# screen.tracer(0)とすると、描画処理が即座に反映されず、非常に高速になります。
screen.tracer(0)

# 大量の描画処理(例: 円の集合)
t.penup()
for i in range(-200, 201, 50):
    for j in range(-200, 201, 50):
        t.goto(i, j)
        t.pendown()
        t.circle(20)
        t.penup()

# 2. オフにしたアニメーションを更新する
# tracer(0)に設定した場合、描画が終わったらscreen.update()を呼び出して画面を更新する必要があります。
screen.update()

# 少し間を置いて、今度は遅いアニメーションで描画
t.goto(0, 0)
t.clear() # 画面をクリア

# 3. アニメーションをオンに戻し、ステップ数を設定する
# screen.tracer(n)で、nステップごとに画面を更新します。nが大きいほど更新頻度が低くなります。
screen.tracer(10) # 10ステップごとに更新

# アニメーションが見えるように描画
for i in range(36):
    t.forward(100)
    t.stamp() # タートルの形状をスタンプとして残す
    t.backward(100)
    t.right(10)

screen.mainloop()

解説

  • screen.tracer(10): 10回描画コマンドが実行されるごとに画面を更新します。これにより、アニメーションのステップが見やすくなります。
  • screen.update(): tracer(0)でオフにしたアニメーションを、この関数が呼ばれた時点で一括で画面に反映します。高速描画に非常に便利です。
  • screen.tracer(0): アニメーションを完全にオフにします。タートルは描画コマンドを実行しますが、画面には表示されません。

イベント処理(キーボード入力とマウスクリック)

ユーザーの操作に応じてタートルを動かすインタラクティブなプログラムの例です。

import turtle

screen = turtle.Screen()
screen.title("キーボードとマウスクリックイベント")
screen.setup(width=500, height=500)

t = turtle.Turtle()
t.shape("turtle")
t.speed(0) # タートルの速度を速く設定

# 1. キーイベントを処理する関数を定義
def move_forward():
    t.forward(20)

def turn_left():
    t.left(30)

def turn_right():
    t.right(30)

def clear_drawing():
    t.clear()
    t.penup()
    t.home() # 原点に戻る
    t.pendown()

# 2. マウスクリックイベントを処理する関数を定義
def handle_click(x, y):
    """画面がクリックされたときに呼び出される関数"""
    print(f"画面がクリックされました: ({x}, {y})")
    t.penup()
    t.goto(x, y)
    t.pendown()
    t.dot(10, "red") # クリック位置に赤い点を打つ

# 3. イベントハンドラを登録
screen.onkey(move_forward, "Up")      # 上矢印キーで前進
screen.onkey(turn_left, "Left")      # 左矢印キーで左回転
screen.onkey(turn_right, "Right")    # 右矢印キーで右回転
screen.onkey(clear_drawing, "c")     # 'c' キーで描画クリア

screen.onclick(handle_click) # 画面クリックでhandle_clickを呼び出す

# 4. キーイベントをリッスンするよう画面に指示する
# onkey()を使用する前に必ず呼び出す必要があります。
screen.listen()

# 5. クリックでウィンドウを終了するオプション (テスト用)
# screen.exitonclick() # クリックされるまで待機し、クリックされたらプログラムを終了する

screen.mainloop()

解説

  • screen.exitonclick(): screen.mainloop()の代わりに使用できます。この場合、画面がクリックされるとプログラムが終了します。開発中に素早く終了させたい場合に便利です。
  • screen.listen(): キーボードイベントを監視するようScreenオブジェクトに指示します。onkeyを使用する場合は必須です。
  • screen.onclick(fun, btn=1): btnで指定されたマウスボタン(デフォルトは左ボタン)が画面をクリックされたときにfun関数を呼び出します。funにはクリックされたX, Y座標が引数として渡されます。
  • screen.onkey(fun, key): keyが押されたときにfun関数を呼び出すように設定します。funには関数そのもの(move_forward)を渡し、move_forward()のように呼び出し結果を渡さないように注意してください。

タイマーイベント (ontimer)

一定時間ごとに処理を繰り返すタイマー機能を使って、簡単なアニメーションを作成します。

import turtle

screen = turtle.Screen()
screen.title("タイマーを使ったアニメーション")
screen.setup(width=400, height=400)
screen.bgcolor("black")

t = turtle.Turtle()
t.shape("circle")
t.color("yellow")
t.penup()
t.goto(0, 0)

# アニメーションのステップを管理する変数
step = 0
speed = 5 # 移動速度
max_steps = 200 # アニメーションの総ステップ数

def animate_dot():
    global step

    if step < max_steps:
        # ドットを少し動かす
        t.forward(speed)
        t.right(5) # 少し回転させる

        # 次の呼び出しをスケジュール
        # screen.ontimer(関数, ミリ秒)で、指定ミリ秒後に一度だけ関数を呼び出します。
        # 連続したアニメーションにするには、関数自身の中でontimerを再帰的に呼び出す必要があります。
        screen.ontimer(animate_dot, 50) # 50ミリ秒後に再度animate_dotを呼び出す
        step += 1
    else:
        print("アニメーション終了!")
        screen.bye() # ウィンドウを閉じる

# アニメーションを開始
animate_dot()

screen.mainloop()
  • screen.bye(): turtleグラフィックスシステムを終了し、ウィンドウを閉じます。これはmainloop()を終了させる方法の一つです。
  • 継続的なアニメーションを作成するには、アニメーション関数(この例ではanimate_dot)の内部でscreen.ontimerを再度呼び出すことで、次のアニメーションフレームをスケジュールします。
  • screen.ontimer(fun, t): tミリ秒後に一度だけfun関数を呼び出すようスケジュールします。


ここでは、TurtleScreen/Screenのメソッドと対応する関数に関連するプログラミングの代替方法について説明します。

turtleモジュールは、主に以下の2つのスタイルで利用できます。

  1. 手続き型インターフェース (Procedure-oriented interface)
  2. オブジェクト指向インターフェース (Object-oriented interface)

これらはどちらも同じ機能を提供しますが、使い方が異なります。また、turtleの限界を超えてより高度なグラフィック処理を求める場合の代替ライブラリについても触れます。

手続き型インターフェース (turtle モジュールレベルの関数を使用)

これは、最も手軽にturtleを使い始める方法です。turtleモジュールをインポートするだけで、turtle.forward()turtle.bgcolor()のように、直接モジュール名を使って関数を呼び出します。この場合、ScreenオブジェクトやTurtleオブジェクトを明示的に作成する必要はありません。モジュールが内部でデフォルトのScreenTurtleのインスタンスを自動的に作成し、それらを操作します。

特徴

  • 制限
    複数のタートルを扱いたい場合や、より複雑な画面管理を行いたい場合には不向きです。デフォルトの単一の画面と単一のタートルしか操作できません。
  • 簡単
    ScreenTurtleのオブジェクトを意識する必要がありません。
  • シンプル
    最も少ないコードで描画を開始できます。


import turtle

# 画面の背景色を変更 (モジュールレベル関数)
turtle.bgcolor("lightgreen")

# ウィンドウのタイトルを設定 (モジュールレベル関数)
turtle.title("手続き型インターフェースの例")

# タートルの移動 (モジュールレベル関数)
turtle.forward(100)
turtle.left(90)
turtle.forward(100)

# ウィンドウを開いたままにする (モジュールレベル関数)
turtle.done() # または turtle.mainloop()

Screenメソッドとの関係
turtle.bgcolor("lightgreen")は、内部的にはデフォルトで作成されたScreenオブジェクトのbgcolor()メソッド(例: _screen.bgcolor("lightgreen"))を呼び出しています。他の画面関連のモジュールレベル関数も同様です。

オブジェクト指向インターフェース (Screen および Turtle オブジェクトを使用)

こちらがより柔軟で、複数のタートルを扱ったり、特定のタートルの動作を独立して制御したりする場合に推奨される方法です。明示的にScreenオブジェクトとTurtleオブジェクトを作成し、それらのインスタンスメソッドを呼び出します。

特徴

  • 推奨
    大規模なプログラムや複雑なグラフィックスを作成する際に、コードの可読性と管理性を高めます。
  • 柔軟性
    複数のTurtleオブジェクトを同じScreen上で作成し、それぞれ異なる動作をさせることができます。
  • 明示的
    どのオブジェクトを操作しているかが明確になります。


import turtle

# Screenオブジェクトを明示的に作成
my_screen = turtle.Screen()
my_screen.title("オブジェクト指向インターフェースの例")
my_screen.bgcolor("pink")
my_screen.setup(width=700, height=500)

# Turtleオブジェクトを明示的に作成
# 同じ画面上で複数のタートルを作成できる
turt_red = turtle.Turtle()
turt_red.color("red")
turt_red.shape("turtle")
turt_red.pensize(3)
turt_red.forward(100)

turt_blue = turtle.Turtle()
turt_blue.color("blue")
turt_blue.shape("circle")
turt_blue.penup()
turt_blue.goto(-100, 50)
turt_blue.pendown()
turt_blue.circle(50)

# 画面のイベントループを開始
my_screen.mainloop()

Screenオブジェクトの取得
Turtleオブジェクトを作成すると、そのタートルが属するScreenオブジェクトはt.screen属性からアクセスできます。

import turtle

t = turtle.Turtle()
# タートルからそのScreenオブジェクトを取得
current_screen = t.screen

current_screen.bgcolor("yellow")
current_screen.title("タートルから画面にアクセス")
t.forward(50)

current_screen.mainloop()

Tkinterとの直接的な連携 (tkinter.Canvas と turtle.RawTurtle/turtle.TurtleScreen)

turtleモジュールは内部的にPythonの標準GUIライブラリであるTkinterの上に構築されています。そのため、より高度なGUIアプリケーションの一部としてturtleの描画機能を組み込みたい場合や、複数の独立したturtle描画領域を持つウィンドウを作成したい場合は、直接TkinterのCanvasウィジェットをturtle.TurtleScreenに渡し、そのTurtleScreen上にturtle.RawTurtleを配置するという方法があります。

この方法は、通常のturtleの使用法よりも複雑ですが、Tkinterの持つ柔軟性を最大限に活用できます。

特徴

  • 複雑
    Tkinterの知識が必要となり、コード量が大幅に増えます。
  • 複数ウィンドウ/キャンバス
    単一のPythonプログラム内で複数のturtle描画領域を持つウィンドウを作成できます。
  • 高度な統合
    turtle描画を他のTkinterウィジェット(ボタン、テキストボックスなど)と組み合わせることができます。

例 (概念)

import tkinter as tk
import turtle

# Tkinterのルートウィンドウを作成
root = tk.Tk()
root.title("TkinterとTurtleの連携例")

# TkinterのCanvasウィジェットを作成
# このCanvasがturtleの描画領域となる
canvas1 = tk.Canvas(root, width=400, height=300, bg="lightgray")
canvas1.pack(side=tk.LEFT)

canvas2 = tk.Canvas(root, width=400, height=300, bg="pink")
canvas2.pack(side=tk.RIGHT)

# 各CanvasにTurtleScreenを紐付ける
screen1 = turtle.TurtleScreen(canvas1)
screen2 = turtle.TurtleScreen(canvas2)

# 各Screen上にRawTurtleを作成(標準のturtle.Turtleとは異なる)
t1 = turtle.RawTurtle(screen1)
t1.color("green")
t1.pensize(2)
t1.forward(100)
t1.left(90)
t1.circle(50)

t2 = turtle.RawTurtle(screen2)
t2.color("purple")
t2.pensize(4)
t2.penup()
t2.goto(-50, -50)
t2.pendown()
for _ in range(3):
    t2.forward(100)
    t2.left(120)

# Tkinterのメインループを開始
root.mainloop()

# 注意: この方法ではscreen.mainloop()やturtle.done()は不要で、
# Tkinterのroot.mainloop()がイベント処理を管理します。

解説

  • turtle.RawTurtle(screen_object): 特定のTurtleScreenインスタンス上で動作するRawTurtleのインスタンスを作成します。通常のturtle.Turtle()は、内部でデフォルトのScreenを作成しますが、RawTurtleは既存のTurtleScreenと結びつけます。
  • turtle.TurtleScreen(canvas_object): 作成したtkinter.Canvasオブジェクトを引数として渡し、そのキャンバス上にTurtleScreenのインスタンスを構築します。
  • tkinter.Canvas(): Tkinterの描画領域となるキャンバスを作成します。

turtle以外のグラフィックスライブラリ

turtleは学習には最適ですが、より高度なゲーム開発、データ可視化、または複雑なGUIアプリケーションには限界があります。そのような場合、以下の代替ライブラリを検討します。

  • PyQt / PySide, Kivy, wxPython

    • 用途
      よりリッチで複雑なGUIアプリケーション開発。
    • 特徴
      クロスプラットフォーム対応で、プロフェッショナルな見た目のGUIアプリケーションを構築できます。Tkinterよりも高機能で、多くのウィジェットと高度なカスタマイズ性を提供します。
    • 学習コスト
      比較的高度で、大規模なアプリケーション開発に適しています。
  • Tkinter (直接使用)

    • 用途
      軽量なGUIアプリケーション開発。
    • 特徴
      Python標準で含まれるため、追加インストール不要。ボタン、テキストボックス、メニューなどのウィジェットと、Canvasウィジェットによる図形描画が可能です。turtleの基盤でもあります。
    • 学習コスト
      GUIプログラミングの基礎を学ぶのに適しています。
  • Matplotlib

    • 用途
      データ可視化、科学技術計算のグラフ描画。
    • 特徴
      折れ線グラフ、棒グラフ、散布図、3Dプロットなど、多様なグラフを高品質で生成できます。アニメーション機能も持ちますが、リアルタイムのインタラクティブな描画やゲームには不向きです。
    • 学習コスト
      特定の目的(データ可視化)においては、非常に強力で標準的なライブラリです。
    • 用途
      主に2Dゲーム開発。
    • 特徴
      高速な描画、スプライト管理、イベント処理、サウンド再生など、ゲームに必要な機能が豊富に揃っています。turtleよりもはるかに低レベルで直接的な描画制御が可能です。
    • 学習コスト
      turtleよりは高いですが、ゲーム開発の入門としては人気です。
  • turtleの限界を超えて、ゲームや本格的なGUIアプリを作るなら
    Pygame、Matplotlib、Tkinter(直接)、PyQtなどの専門ライブラリ
  • Tkinterアプリにturtle描画を組み込んだり、複数のturtleウィンドウを作ったりするなら
    Tkinterとturtle.RawTurtleの直接連携
  • 複数のタートルを制御したり、コードを整理したりするなら
    オブジェクト指向インターフェース (screen = turtle.Screen(), t = turtle.Turtle())
  • 最もシンプルに始めるなら
    手続き型インターフェース (turtle.bgcolor(), turtle.forward())