タートルグラフィックスの画面サイズ制御: window_height()でできること

2025-06-06

Pythonのturtleモジュールにおけるturtle.window_height()は、タートルグラフィックスが描画されるウィンドウの現在の高さをピクセル単位で取得する関数です。

もう少し詳しく説明すると、以下のようになります。



turtle.window_height() に関連する一般的なエラーとトラブルシューティング

NameError: name 'turtle' is not defined または AttributeError: module 'turtle' has no attribute 'window_height'

  • トラブルシューティング
    • コードの先頭に必ず import turtle を記述しているか確認してください。
    • もし import turtle as 名前 のように別名でインポートしている場合は、その別名を使って関数を呼び出しているか確認してください。
    • それでも解決しない場合、IDEやエディタを再起動してみるか、別のPython環境(コマンドプロンプトやターミナルからの直接実行など)で試してみてください。
  • エラーの原因
    • import turtle を忘れている。
    • turtleを別の名前でインポートしている(例: import turtle as t)のに、turtle.window_height()と呼び出している。この場合、t.window_height()と記述する必要があります。
    • Pythonの環境(特にIDEや一部のエディタ)で、モジュールのインポートが正しく行われていない、またはキャッシュの問題。

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

  • トラブルシューティング
    • プログラムの最後に turtle.done() または turtle.Screen().exitonclick() を追加してください。これにより、ウィンドウが閉じるまでプログラムが待機します。
      import turtle
      screen = turtle.Screen()
      # 描画処理
      height = screen.window_height()
      print(f"Window height: {height}")
      turtle.done() # または screen.exitonclick()
      
    • 特にインタラクティブな環境(IDLEなど)でない限り、turtle.Screen() オブジェクトを明示的に作成し、それを通じて操作することが推奨されます。
  • エラーの原因
    turtle.window_height()自体がエラーを出すわけではありませんが、この関数を使う前提となるTurtleグラフィックスのウィンドウが適切に表示されていない場合に、意図しない動作となることがあります。
    • プログラムが終了すると同時にウィンドウも閉じられるため、描画内容を確認する前に閉じてしまう。
    • turtle.Screen() オブジェクトを適切に作成していない。

取得した高さが期待と異なる

  • トラブルシューティング
    • コード内で turtle.Screen().setup(width=幅, height=高さ) を使って明示的にウィンドウサイズを設定し、その設定した高さがwindow_height()で取得できるか確認してください。
    • 実行中に手動でウィンドウのサイズを変更し、その後にwindow_height()を呼び出して値が変化するか確認することで、関数が正しく動作していることを検証できます。
    • OSのディスプレイ設定(スケーリングなど)を確認してみる(これは非常に稀なケースです)。
  • エラーの原因
    • turtle.setup()などで明示的にウィンドウサイズを設定していない場合、デフォルトのサイズが使われます。環境によってデフォルトサイズが異なることがあります。
    • ユーザーが手動でウィンドウサイズを変更した場合、その変更が即座に反映されます。
    • 画面の解像度やスケーリング設定が影響している可能性は低いですが、ごく稀にOSレベルの設定が影響することも考えられます。

_tkinter モジュールが見つからない (No module named '_tkinter')

  • トラブルシューティング
    • Tkinterがインストールされているか確認してください。多くのPythonディストリビューションではデフォルトで含まれていますが、そうでない場合は別途インストールが必要です。
    • Ubuntu/Debian系
      sudo apt-get install python3-tk (Python 3の場合)
    • Fedora/CentOS系
      sudo yum install python3-tkinter または sudo dnf install python3-tkinter
    • Windows/macOS
      通常はPythonの公式インストーラに含まれています。もしこのエラーが出る場合は、Pythonを再インストールし、Tkinterのオプションが有効になっていることを確認してください。
  • エラーの原因
    turtleモジュールは、グラフィック描画にTkinterというGUIライブラリを使用しています。Pythonのインストール時にTkinterが適切に含まれていない場合に発生します。これは特にLinux環境や、ミニマルなPythonインストールで起こりやすいです。
  • turtle.Screen() オブジェクトの利用
    turtle.window_height() のようにモジュールレベルで直接呼び出せる関数もありますが、多くの場合は screen = turtle.Screen() のようにScreenオブジェクトを作成し、screen.window_height() のようにオブジェクトのメソッドとして呼び出す方が、よりオブジェクト指向的で、プログラムの構造が明確になり、他の画面関連の操作と一貫性が保たれます。
  • Pythonのバージョン
    使用しているPythonのバージョン(例: Python 3.9、3.10など)によっては、ごく稀に挙動が異なる場合があります。もし問題が解決しない場合、バージョン依存の問題がないか公式ドキュメントで確認するのも一つの手です。
  • エラーメッセージをよく読む
    Pythonのエラーメッセージは非常に情報量が多く、どこで何が間違っているかを示してくれます。NameErrorAttributeErrorTypeErrorなどの種類と、それがどの行で発生したかを確認しましょう。
  • 最小限の再現可能なコード
    エラーが発生した場合、問題を特定するために、turtle.window_height()を使用している部分だけを含む最小限のコードスニペットを作成してみてください。これにより、問題が他の複雑なコードに隠れていないことを確認できます。


例1: ウィンドウの高さの取得と表示

これは最も基本的な使用例で、ウィンドウの現在の高さを取得してコンソールに表示します。

import turtle

# 1. 画面オブジェクトの取得
#    通常、turtleグラフィックスのウィンドウはScreenオブジェクトを介して操作します。
screen = turtle.Screen()

# 2. ウィンドウのサイズを設定(任意)
#    設定しない場合、デフォルトのサイズ(通常800x600ピクセルなど)になります。
screen.setup(width=600, height=400) # 幅600px、高さ400pxに設定

# 3. ウィンドウの高さを取得
#    screenオブジェクトのメソッドとして呼び出すのが推奨されます。
current_height = screen.window_height()

# 4. 取得した高さを表示
print(f"現在のウィンドウの高さ: {current_height} ピクセル")

# 5. タートルを描画(任意)
t = turtle.Turtle()
t.penup() # ペンを上げて移動
t.goto(0, current_height / 2 - 50) # ウィンドウ上部から少し下に移動
t.pendown() # ペンを下ろして描画開始
t.write("Hello Turtle!", align="center", font=("Arial", 24, "normal"))

# 6. ウィンドウを閉じるまで待機
#    これがないと、プログラムがすぐに終了し、ウィンドウも閉じてしまいます。
turtle.done()

解説

  • 取得した高さを使って、ウィンドウの上部(Y座標が正の方向)にテキストを表示する例も含まれています。タートルの座標系は中央が(0,0)なので、高さの半分がウィンドウの上端になります。
  • その後、screen.window_height() でその高さを取得し、print() で出力しています。
  • screen.setup(width=600, height=400) で明示的に高さを設定しています。

例2: ウィンドウの高さに基づいて描画位置を調整する

ウィンドウの高さが変更されても、描画される要素の位置を相対的に調整したい場合に役立ちます。

import turtle

screen = turtle.Screen()
screen.setup(width=800, height=600) # 初期サイズを設定

# タートルを作成
t = turtle.Turtle()
t.speed(0) # 最速
t.hideturtle() # タートルアイコンを非表示

# ウィンドウの高さに基づいて描画する関数
def draw_elements_based_on_height():
    t.clear() # 描画内容をクリア
    
    window_h = screen.window_height()
    window_w = screen.window_width() # 幅も取得しておくと便利

    # ウィンドウの中央より少し下
    t.penup()
    t.goto(0, -window_h / 4) 
    t.pendown()
    t.dot(20, "blue") # 青い点

    # ウィンドウの上部近く
    t.penup()
    t.goto(0, window_h / 2 - 50) # 上端から50px下
    t.pendown()
    t.write(f"高さ: {window_h}px", align="center", font=("Arial", 18, "normal"))

    # ウィンドウの下部近く
    t.penup()
    t.goto(0, -window_h / 2 + 50) # 下端から50px上
    t.pendown()
    t.write("ウィンドウ下部", align="center", font=("Arial", 18, "normal"))

# 初回描画
draw_elements_based_on_height()

# ウィンドウのサイズが変更されたときにイベントを発生させる
# onresizeは直接サポートされていないので、タイマーで定期的にチェックするなどの工夫が必要です。
# または、手動でウィンドウをリサイズしてから関数を呼び出す。

# 例として、ウィンドウをリサイズしてからEnterキーを押すと再描画されるようにする
print("ウィンドウをリサイズしてください。その後、コンソールでEnterキーを押してください。")
input() # ユーザーがEnterを押すまで待機

# リサイズ後に再描画
draw_elements_based_on_height()
print(f"リサイズ後の高さ: {screen.window_height()} ピクセル")


turtle.done()

解説

  • onresize イベントの直接的なサポートがないため、ここではユーザーがEnterを押すことで再描画されるようにしています。実際のアプリケーションでは、より高度なイベントハンドリングや定期的なチェックが必要になることがあります。
  • これにより、ユーザーが手動でウィンドウのサイズを変更した場合でも、要素がウィンドウに対して相対的に正しい位置に表示されるようにできます。
  • draw_elements_based_on_height() 関数内で screen.window_height() を呼び出し、その値を使って点の位置やテキストのY座標を計算しています。

ゲームや複雑なグラフィックスで、描画エリアの境界を動的に計算する際に使われます。

import turtle

screen = turtle.Screen()
screen.setup(width=800, height=600)
screen.bgcolor("lightgrey")

t = turtle.Turtle()
t.speed(0)
t.hideturtle()
t.penup()

# 描画可能な境界線を描く関数
def draw_boundary():
    t.clear()
    
    current_width = screen.window_width()
    current_height = screen.window_height()

    # 境界線の描画
    t.goto(-current_width / 2, -current_height / 2) # 左下
    t.pendown()
    t.goto(current_width / 2, -current_height / 2)  # 右下
    t.goto(current_width / 2, current_height / 2)   # 右上
    t.goto(-current_width / 2, current_height / 2)  # 左上
    t.goto(-current_width / 2, -current_height / 2) # 左下に戻る
    t.penup()

    # 中央にテキスト
    t.goto(0, 0)
    t.write(f"幅: {current_width}px, 高さ: {current_height}px", align="center", font=("Arial", 16, "normal"))

# 初回描画
draw_boundary()

# ウィンドウのサイズ変更イベントを捕捉する(やや高度なテクニック)
# Tkinterのrootウィンドウを取得し、<Configure>イベントをバインドします。
# これにより、ウィンドウがリサイズされるたびにdraw_boundaryが呼び出されます。
root = screen._root # Tkinterのrootウィンドウを取得
root.bind("<Configure>", lambda e: draw_boundary())

print("ウィンドウのサイズを変更してみてください。境界線と表示される値がリアルタイムで更新されます。")

turtle.done()
  • 重要な点
    screen._root.bind("<Configure>", lambda e: draw_boundary()) という行があります。これは、turtleモジュールが内部で利用しているTkinterライブラリの機能を使って、ウィンドウのサイズが変更されるイベント(<Configure>)を捕捉し、そのたびにdraw_boundary()関数を呼び出すように設定しています。これにより、リアルタイムで描画内容が更新されるようになります。これはturtleモジュールの公式APIではないため、_rootのような非公開属性を使っていますが、一般的に利用されるテクニックです。
  • この例では、screen.window_height()screen.window_width() の両方を使用して、ウィンドウの現在の境界線を描画しています。


ここでは、**「turtle.window_height()の直接的な使用を避ける、または他の目的でウィンドウの高さを扱う」**という観点から、代替方法を説明します。

screen.setup()で初期高さを固定し、その値を利用する

これは代替というよりは、window_height()を呼び出す必要がないケースです。

  • コード例

    import turtle
    
    # 設定するウィンドウの高さ
    INITIAL_WINDOW_HEIGHT = 400
    INITIAL_WINDOW_WIDTH = 600
    
    screen = turtle.Screen()
    screen.setup(width=INITIAL_WINDOW_WIDTH, height=INITIAL_WINDOW_HEIGHT)
    
    # 描画に設定した高さを使用
    t = turtle.Turtle()
    t.penup()
    # ウィンドウの上端にテキストを表示 (設定した高さを使用)
    t.goto(0, INITIAL_WINDOW_HEIGHT / 2 - 20)
    t.write(f"設定された高さ: {INITIAL_WINDOW_HEIGHT}px", align="center", font=("Arial", 16, "normal"))
    
    turtle.done()
    
  • 欠点

    • ユーザーが手動でウィンドウサイズを変更した場合、プログラムがその変更を認識できません。
    • ウィンドウの現在の実際の高さではなく、設定した高さに依存します。
  • 利点

    • コードがシンプルになります。
    • 常に同じ固定値が使われるため、予期せぬウィンドウサイズ変更による問題が起きません。
  • 考え方
    プログラムが開始する際に、screen.setup()を使ってウィンドウの幅と高さを明示的に設定し、その設定した値自体をプログラム内で変数として保持しておけば、window_height()を呼び出す手間が省けます。ウィンドウサイズが実行中に変更されない(または変更されても対応する必要がない)場合に有効です。

Tkinterのジオメトリ情報から高さを取得する

turtleモジュールは内部的にtkinterというPythonのGUIライブラリを使用しています。そのため、tkinterの機能を使ってウィンドウのジオメトリ情報(サイズや位置)を直接取得することも可能です。

  • 欠点

    • turtleモジュールの内部実装(_root属性など)に踏み込むため、非公開APIの利用となり、将来的なバージョンの変更で動作しなくなる可能性があります。
    • tkinterの知識が必要になります。
    • 一般的にはturtle.window_height()で十分なため、過度な複雑さをもたらすことがあります。
  • 利点

    • turtleモジュールに依存せず、より低レベルな情報にアクセスできます。
    • turtle.window_height()と同じく、常に現在の実際のウィンドウの高さを取得できます。
  • 考え方
    turtle.Screen()オブジェクトから基盤となるtkinter.Tkオブジェクトにアクセスし、そのgeometry()メソッドやwinfo_height()メソッドを利用して情報を取得します。

これは「高さを取得する」直接的な代替ではありませんが、「高さの変更に対応する」という点では代替的なアプローチです。

  • コード例
    上記の「例3: 動的な描画エリアの計算」で示したものがこれに当たります。

    import turtle
    
    screen = turtle.Screen()
    screen.setup(width=800, height=600)
    screen.bgcolor("lightgrey")
    
    t = turtle.Turtle()
    t.speed(0)
    t.hideturtle()
    t.penup()
    
    def draw_boundary():
        t.clear()
    
        current_width = screen.window_width()
        current_height = screen.window_height() # ここで高さを取得
    
        # 境界線を描画(高さに基づいて計算)
        t.goto(-current_width / 2, -current_height / 2) # 左下
        t.pendown()
        t.goto(current_width / 2, -current_height / 2)  # 右下
        t.goto(current_width / 2, current_height / 2)   # 右上
        t.goto(-current_width / 2, current_height / 2)  # 左上
        t.goto(-current_width / 2, -current_height / 2) # 左下に戻る
        t.penup()
    
        t.goto(0, 0)
        t.write(f"幅: {current_width}px, 高さ: {current_height}px", align="center", font=("Arial", 16, "normal"))
    
    draw_boundary()
    
    # Tkinterのrootウィンドウを取得し、<Configure>イベントをバインド
    root = screen._root 
    root.bind("<Configure>", lambda e: draw_boundary()) # サイズ変更時にdraw_boundaryを呼び出す
    
    print("ウィンドウのサイズを変更してみてください。境界線と表示される値がリアルタイムで更新されます。")
    
    turtle.done()
    
  • 欠点

    • tkinterの知識が必要で、_root属性のような非公開APIの利用を伴います。
    • turtle.window_height()の呼び出し自体は避けられません。
  • 利点

    • リアルタイムにウィンドウサイズ変更に対応できます。
    • ユーザー体験が向上します。
  • 考え方
    tkinterのイベントシステムを利用して、ウィンドウのサイズが変更されたときに特定の関数を呼び出すように設定します。その関数の中でturtle.window_height()を呼び出せば、常に最新の高さで処理を実行できます。

  • リアルタイムな変更への対応
    tkinterのイベントバインディング (_root.bind("<Configure>", ...)) と組み合わせる。
    • これもturtle.window_height()の直接的な代替ではなく、それと組み合わせて動的な挙動を実現する手法です。
  • 低レベルなアクセスが必要な場合
    tkinterのジオメトリ情報 (_root.winfo_height()) を利用する。
    • 非公開APIの使用なので注意が必要ですが、特定の高度なニーズには対応できます。
  • 固定サイズの場合の代替
    screen.setup()で設定した値を直接利用する。
    • ウィンドウがリサイズされないことが確実な場合にシンプルさを追求できます。
  • 最も推奨される方法
    turtle.Screen().window_height()
    • これがturtleモジュールの意図された、最も安全で直接的な方法です。
    • ほとんどのユースケースでこれで十分です。