初心者必見!Python Turtleのresizemode活用術と実践サンプルコード集
turtle
モジュールは、グラフィック描画を簡単に行うためのPythonの標準ライブラリです。turtle.resizemode()
関数は、タートル(描画を行うカーソル)の形状がウィンドウのサイズ変更時にどのように振る舞うかを制御するために使用されます。
この関数は引数を取らず、タートルが現在どのリサイズモードであるかを返します。また、引数として文字列を渡すことで、リサイズモードを設定することもできます。
使用例
import turtle
# タートルの描画画面を設定
screen = turtle.Screen()
screen.setup(width=600, height=400)
# タートルの作成
t = turtle.Turtle()
# 現在のリサイズモードを表示(デフォルトは通常 'noresize')
print(f"現在のリサイズモード: {turtle.resizemode()}")
# リサイズモードを 'user' に設定
turtle.resizemode("user")
print(f"新しいリサイズモード: {turtle.resizemode()}")
# リサイズモードを 'auto' に設定
turtle.resizemode("auto")
print(f"新しいリサイズモード: {turtle.resizemode()}")
# リサイズモードを 'noresize' に戻す
turtle.resizemode("noresize")
print(f"新しいリサイズモード: {turtle.resizemode()}")
# 画面を閉じる
screen.exitonclick()
リサイズモードの種類
turtle.resizemode()
で設定できるモードは以下の3種類です。
-
- このモードでは、タートルの形状はウィンドウのサイズが変更されても変化しません。タートルの見た目のサイズは固定されたままです。
- ほとんどの場合、このモードがデフォルトであり、特にタートルの形状が画面のサイズに合わせて拡大・縮小する必要がない場合に適しています。
-
"auto"
- このモードでは、タートルの形状は、描画が行われるキャンバス(ウィンドウ)のサイズに合わせて自動的に拡大・縮小されます。
- 例えば、ウィンドウを大きくするとタートルの形状も大きく表示され、小さくするとタートルの形状も小さく表示されます。これは、タートルの相対的なサイズを画面に対して一定に保ちたい場合に便利です。
-
"user"
- このモードでは、タートルの形状の拡大・縮小は、プログラマが明示的に制御することになります。
- 具体的には、
turtle.turtlesize()
メソッドを使用してタートルの形状のストレッチ係数(伸縮率)を設定することで、手動でサイズを変更できます。このモードに設定するだけでは自動的なサイズ変更は行われません。 - 例:
t.turtlesize(stretch_wid=2, stretch_len=2, outline=1)
turtle.resizemode()
は、turtle
グラフィックのタートルが、描画ウィンドウのサイズ変更時にどのように自身の形状を調整するかを決定するための機能です。
"user"
: タートルの形状の拡大・縮小はturtlesize()
で手動で制御する。"auto"
: タートルの形状はウィンドウサイズに合わせて自動的に拡大・縮小される。"noresize"
: タートルの形状は変化しない(固定サイズ)。
turtle.resizemode()
は比較的シンプルで、大きなエラーは起こりにくい関数ですが、それでもいくつかの一般的な問題や誤解が生じることがあります。
モード名のタイプミス (TypeError または無効なモード設定)
エラーの例
import turtle
turtle.resizemode("autoo") # "auto" のタイプミス
# あるいは
turtle.resizemode("custom") # 存在しないモード名
発生する可能性のあるエラー
- あるいは、単にモードが設定されずに、以前のモード(デフォルトの
"noresize"
など)のままになることがあります。これはエラーメッセージが出ないため、意図した動作にならない「サイレントエラー」となる可能性があります。 TypeError: rmode must be one of "auto", "user", or "noresize"
のようなメッセージが出る可能性があります。
トラブルシューティング
"auto"
,"user"
,"noresize"
のいずれかの正しい文字列を引数として渡しているか確認してください。大文字と小文字も区別されます。
resizemode("user")を設定したのにタートルのサイズが変わらない
問題の現象
turtle.resizemode("user")
を設定したのに、ウィンドウのサイズを変更してもタートルの形状が自動的に拡大・縮小されない。
原因
"user"
モードは、タートルのサイズ変更をプログラマが手動で制御するためのモードです。このモードに設定するだけでは、タートルは自動的にリサイズされません。タートルのサイズを実際に変更するには、turtle.shapesize()
(またはturtle.turtlesize()
) メソッドを別途呼び出す必要があります。
トラブルシューティング
turtle.resizemode("user")
を設定した後、turtle.shapesize(stretch_wid=..., stretch_len=...)
などを使ってタートルのサイズを明示的に設定しているか確認してください。import turtle screen = turtle.Screen() t = turtle.Turtle() turtle.resizemode("user") # タートルの形状を2倍に拡大 t.shapesize(stretch_wid=2, stretch_len=2) screen.exitonclick()
resizemode("auto")を設定したのにタートルのサイズが変わらない(特殊なケース)
問題の現象
turtle.resizemode("auto")
を設定したのに、タートルの形状がウィンドウサイズに合わせて拡大・縮小されない。
原因(可能性)
"auto"
モードは、タートルの形状がペン先の太さ(pensize()
)に基づいて自動的に調整されることがあります。しかし、特定のカスタムシェイプを使用している場合や、描画以外の方法でタートルを操作している場合など、意図したように動作しないことがあります。また、turtle
モジュールはTkinterの上に構築されているため、Tkinterの描画コンテキストや環境によっては挙動が異なる場合があります。
トラブルシューティング
turtle.Screen().setup()
で明示的に画面サイズを設定している場合、その設定がリサイズ動作に影響している可能性があります。turtle.pensize()
を変更してみて、その変化が"auto"
モードのタートルサイズに影響するかを確認してください。- シンプルなタートル形状(デフォルトの"classic"や"turtle"など)で試してみてください。
turtle.resizemode()を呼び出してもエラーが出ないのに何も変わらない
問題の現象
turtle.resizemode("some_mode")
を呼び出してもエラーは出ないが、タートルの動作や表示に変化が見られない。
原因
- タートルのインスタンスに対して呼び出していない
turtle.resizemode()
はモジュールレベルの関数であり、特定のタートルインスタンスのメソッドではありません(ただし、特定のタートルインスタンスがこのモードの影響を受ける)。しかし、もしsome_turtle_instance.resizemode()
のように呼び出そうとしている場合、それはエラーになるか、意図しない動作をするでしょう。# 誤った例: t = turtle.Turtle() t.resizemode("auto") # AttributeError になる可能性が高い
- 関数の戻り値を使っているだけ
turtle.resizemode()
は引数なしで呼び出すと現在のモードを返します。この戻り値を捨てている場合、モード設定を行っていないことになります。import turtle # これはモードを"auto"に設定するのではなく、現在のモードを取得してそれを"auto"と比較しているだけ if turtle.resizemode() == "auto": print("モードはautoです")
turtle.resizemode()
は、タートル(描画を行うカーソル)の形状が、描画ウィンドウのサイズ変更時にどのように振る舞うかを制御するために使用されます。ここでは、各モードの具体的な動作を示す例を挙げます。
例1: resizemode("noresize")
(デフォルト)
このモードでは、タートルの形状はウィンドウのサイズが変更されても変化しません。タートルの見た目のサイズは固定されたままです。
import turtle
import time
# 描画画面の設定
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("Resizemode: noresize (デフォルト)")
# タートルの作成
t = turtle.Turtle()
t.shape("turtle") # タートルの形状を「カメ」に設定
t.color("blue")
t.shapesize(stretch_wid=3, stretch_len=3, outline=1) # 初期サイズを少し大きめに
# リサイズモードを「noresize」に設定(デフォルトなので明示的に設定しなくても同じ)
turtle.resizemode("noresize")
print(f"現在のリサイズモード: {turtle.resizemode()}")
t.penup()
t.goto(-200, 0)
t.pendown()
t.write("ウィンドウをリサイズしてください", font=("Arial", 16, "normal"))
t.penup()
t.goto(0, -100)
t.pendown()
# ウィンドウをリサイズしても、タートルの形状は変わりません。
# 試すには、このスクリプトを実行し、表示されたウィンドウの端をドラッグしてサイズを変更してみてください。
print("ウィンドウをリサイズしても、タートルの形状は固定されます。")
# ユーザーがウィンドウを閉じるまで待機
screen.exitonclick()
説明
このコードを実行すると、青いカメのタートルが画面に表示されます。ウィンドウのサイズを大きくしたり小さくしたりしても、カメの見た目の大きさは変わりません。これが"noresize"
の動作です。
例2: resizemode("auto")
このモードでは、タートルの形状は、描画が行われるキャンバス(ウィンドウ)のサイズに合わせて自動的に拡大・縮小されます。
import turtle
import time
# 描画画面の設定
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("Resizemode: auto")
# タートルの作成
t = turtle.Turtle()
t.shape("turtle")
t.color("red")
t.shapesize(stretch_wid=3, stretch_len=3, outline=1) # 初期サイズを少し大きめに
# リサイズモードを「auto」に設定
turtle.resizemode("auto")
print(f"現在のリサイズモード: {turtle.resizemode()}")
t.penup()
t.goto(-200, 0)
t.pendown()
t.write("ウィンドウをリサイズしてください", font=("Arial", 16, "normal"))
t.penup()
t.goto(0, -100)
t.pendown()
# ウィンドウをリサイズすると、タートルの形状も自動的に拡大・縮小されます。
# 試すには、このスクリプトを実行し、表示されたウィンドウの端をドラッグしてサイズを変更してみてください。
print("ウィンドウをリサイズすると、タートルの形状も自動的に拡大・縮小されます。")
# ユーザーがウィンドウを閉じるまで待機
screen.exitonclick()
説明
このコードを実行すると、赤いカメのタートルが表示されます。ウィンドウを大きくするとカメも大きく表示され、小さくするとカメも小さく表示されます。これは、タートルの相対的なサイズを画面に対して一定に保ちたい場合に非常に便利です。
例3: resizemode("user")
このモードでは、タートルの形状の拡大・縮小は、プログラマが明示的に制御することになります。turtle.shapesize()
(またはturtle.turtlesize()
) メソッドを使って、手動でサイズを変更します。
この例では、ウィンドウのリサイズイベントを検知し、それに応じてタートルのサイズを手動で調整する方法を示します。
import turtle
# 描画画面の設定
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("Resizemode: user")
# タートルの作成
t = turtle.Turtle()
t.shape("turtle")
t.color("green")
t.shapesize(stretch_wid=3, stretch_len=3, outline=1) # 初期サイズを少し大きめに
# リサイズモードを「user」に設定
turtle.resizemode("user")
print(f"現在のリサイズモード: {turtle.resizemode()}")
t.penup()
t.goto(-200, 0)
t.pendown()
t.write("ウィンドウをリサイズしてください (タートルは自動で変わらない)", font=("Arial", 14, "normal"))
t.penup()
t.goto(0, -100)
t.pendown()
# ウィンドウのリサイズ時に呼び出される関数
def on_window_resize(width, height):
print(f"ウィンドウがリサイズされました: 幅={width}, 高さ={height}")
# ウィンドウの高さに基づいてタートルのサイズを調整する例
# 例えば、ウィンドウの高さが小さいほどタートルも小さくする
# 最小サイズと最大サイズを設定して、極端な変化を防ぐ
min_size = 0.5
max_size = 5.0
# 基準となる高さを決め、それに合わせてスケールを計算
# ここでは、元のウィンドウの高さ400ピクセルを基準とする
scale = height / 400.0
# スケールが範囲内に収まるように調整
scaled_size = max(min_size, min(max_size, scale * 3)) # 元のshapesize(3)を基準に調整
t.shapesize(stretch_wid=scaled_size, stretch_len=scaled_size, outline=1)
# テキストを更新
t.clear() # 前のテキストをクリア
t.penup()
t.goto(-200, 0)
t.pendown()
t.write(f"サイズ: {scaled_size:.2f} (ウィンドウの高さ: {height})", font=("Arial", 14, "normal"))
# ウィンドウのリサイズイベントにハンドラを登録
screen.onresize(on_window_resize)
print("ウィンドウをリサイズしてください。タートルのサイズが手動で調整されます。")
# ユーザーがウィンドウを閉じるまで待機
screen.exitonclick()
説明
この例では、まずturtle.resizemode("user")
を設定します。その後、screen.onresize(on_window_resize)
を使って、ウィンドウがリサイズされるたびにon_window_resize
関数が呼び出されるように設定しています。
on_window_resize
関数の中では、現在のウィンドウの高さに基づいてタートルのshapesize()
を計算し、手動でタートルのサイズを変更しています。これにより、プログラマが望むロジックに基づいてタートルのサイズを動的に変更できます。
turtle.resizemode()
はタートルの形状のリサイズ挙動を制御する便利な関数ですが、特定の状況下では、他の方法でタートルのサイズを管理したり、リサイズに関連する描画の挙動を制御したりすることが考えられます。
主な代替手段としては、以下のようなものがあります。
turtle.shapesize()
(またはturtle.turtlesize()
) を手動で呼び出す- カスタムシェイプを定義し、そのサイズを動的に変更する
- イベントハンドラと組み合わせて描画を再構築する
- 画面の物理的なサイズを考慮した描画を行う
それぞれ詳しく見ていきましょう。
turtle.shapesize() を手動で呼び出す
これは、turtle.resizemode("user")
と組み合わせて使う方法の核心部分ですが、resizemode
を設定せずに、必要に応じてタートルのサイズを明示的に変更することもできます。これは、特定のイベント(例えばキーボード入力やマウスイベント)に基づいてタートルのサイズを変更したい場合に特に有効です。
特徴
resizemode
を"noresize"
(デフォルト)のままにしておき、必要な時だけサイズ変更を行うことが可能。stretch_wid
(幅方向の伸縮率)、stretch_len
(長さ方向の伸縮率)、outline
(アウトラインの太さ)を制御できる。- 最も直接的で簡単な方法。
コード例
import turtle
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("Shapesizeの手動制御")
t = turtle.Turtle()
t.shape("turtle")
t.color("purple")
t.shapesize(stretch_wid=2, stretch_len=2) # 初期サイズ
# 'u' キーを押すとタートルが大きく、'd' キーを押すと小さくなる
def enlarge_turtle():
current_wid, current_len, _ = t.shapesize()
t.shapesize(current_wid * 1.2, current_len * 1.2)
print(f"タートルが大きくなりました: {t.shapesize()}")
def shrink_turtle():
current_wid, current_len, _ = t.shapesize()
t.shapesize(current_wid * 0.8, current_len * 0.8)
print(f"タートルが小さくなりました: {t.shapesize()}")
screen.listen()
screen.onkey(enlarge_turtle, "u") # 'u'キーで拡大
screen.onkey(shrink_turtle, "d") # 'd'キーで縮小
t.penup()
t.goto(0, 100)
t.write("Uキーで拡大、Dキーで縮小", align="center", font=("Arial", 16, "normal"))
screen.exitonclick()
カスタムシェイプを定義し、そのサイズを動的に変更する
turtle
モジュールでは、SVGファイルなどからカスタムシェイプを読み込んだり、座標のリストを使って独自のシェイプを定義したりすることができます。turtle.addshape()
で登録したシェイプは、元の定義のサイズに基づいて拡大・縮小されます。
この方法は、特に複雑な図形をタートルの形状として使いたい場合に有効です。リサイズモードではシェイプそのものが拡大・縮小されますが、カスタムシェイプの定義を変更することで、より細かな制御が可能です。
特徴
- シェイプの元の定義を変更することで、タートルの見た目を根本的に変えることができる。
turtle.register_shape()
やturtle.addshape()
でシェイプを登録し、turtle.shape()
で設定する。- より複雑なタートルの形状を扱える。
コード例 (概念的)
この例は、単純なturtle.shapesize()
の代わりに、座標リストで定義されたカスタムシェイプを動的に変更するアイデアを示します。
import turtle
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("カスタムシェイプの動的変更")
# 三角形のシェイプを定義
original_triangle = ((0, 0), (50, 0), (25, 50))
# シェイプを登録
screen.register_shape("my_triangle", original_triangle)
t = turtle.Turtle()
t.shape("my_triangle") # カスタムシェイプを設定
t.color("orange")
# スケール係数
scale_factor = 1.0
def resize_custom_shape(factor):
global scale_factor
scale_factor *= factor
# 新しい座標を計算
scaled_triangle = tuple([(x * scale_factor, y * scale_factor) for x, y in original_triangle])
# 既存のシェイプを削除し、新しいサイズで再登録
screen.addshape("my_triangle", scaled_triangle) # 同じ名前で登録すると上書きされる
t.shape("my_triangle") # 再度設定して更新を強制
def enlarge_custom_shape():
resize_custom_shape(1.2)
print(f"カスタムシェイプが大きくなりました。現在のスケール: {scale_factor:.2f}")
def shrink_custom_shape():
resize_custom_shape(0.8)
print(f"カスタムシェイプが小さくなりました。現在のスケール: {scale_factor:.2f}")
screen.listen()
screen.onkey(enlarge_custom_shape, "u")
screen.onkey(shrink_custom_shape, "d")
t.penup()
t.goto(0, 100)
t.write("Uキーで拡大、Dキーで縮小(カスタムシェイプ)", align="center", font=("Arial", 14, "normal"))
screen.exitonclick()
イベントハンドラと組み合わせて描画を再構築する
turtle.resizemode("user")
の例でも少し触れましたが、ウィンドウのリサイズイベント (screen.onresize()
) を利用して、単にタートルのサイズを変えるだけでなく、画面全体の描画を再調整することが可能です。これは、タートル以外の要素(線、円、テキストなど)も画面サイズに合わせて調整したい場合に非常に強力な方法です。
特徴
- 複雑なレイアウトやレスポンシブなグラフィックを作成するのに適している。
- タートルだけでなく、描画されたすべての要素を調整できる。
- ウィンドウサイズ変更時に任意のロジックを実行できる。
コード例
import turtle
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("ウィンドウリサイズ時の再描画")
t = turtle.Turtle()
t.shape("arrow")
t.color("blue")
t.speed(0)
t.penup()
t.hideturtle() # 描画専用なのでタートルは非表示に
def draw_elements(width, height):
t.clear() # 画面上のすべての描画をクリア
# 画面中央に円を描く
t.goto(0, -height / 4) # 円の中心Y座標
t.pendown()
t.circle(min(width, height) / 4) # 画面の小さい方の辺に合わせて円の大きさを調整
t.penup()
# 画面の四隅にテキストを描く
font_size = max(10, min(20, int(min(width, height) / 30))) # 画面サイズに応じてフォントサイズ調整
t.goto(-width/2 + 20, height/2 - 40)
t.write(f"左上 ({width}x{height})", font=("Arial", font_size, "normal"))
t.goto(width/2 - 100, height/2 - 40)
t.write("右上", font=("Arial", font_size, "normal"))
t.goto(-width/2 + 20, -height/2 + 20)
t.write("左下", font=("Arial", font_size, "normal"))
t.goto(width/2 - 60, -height/2 + 20)
t.write("右下", font=("Arial", font_size, "normal"))
# 初期描画
draw_elements(600, 400)
# ウィンドウのリサイズイベントにハンドラを登録
screen.onresize(draw_elements)
print("ウィンドウをリサイズしてください。描画内容が自動的に再調整されます。")
screen.exitonclick()
説明
この例では、on_window_resize
関数(ここではdraw_elements
)内で、t.clear()
で一度画面をクリアし、現在のウィンドウサイズ(width
, height
)に基づいてすべての要素(円、テキスト)を再描画しています。これにより、ウィンドウサイズが変更されるたびに、描画全体が新しいサイズにフィットするように動的に調整されます。
画面の物理的なサイズを考慮した描画を行う
これはturtle
モジュールの機能というよりは、描画ロジックの設計に関する考え方です。画面の座標系を物理的なサイズ(例:メートル、センチメートル)や、アプリケーションで扱う論理的な単位(例:ゲーム内のグリッド単位)に基づいて設計し、それを画面のピクセル座標にマッピングすることで、リサイズ時のスケーリングをより厳密に制御できます。
turtle
モジュールでは、デフォルトで画面の中心が(0,0)となる座標系を使用しますが、screen.setworldcoordinates()
を使って座標系を再定義することもできます。
特徴
setworldcoordinates()
で仮想的な座標系を設定することで、ピクセルサイズに依存しない描画ロジックを構築できる。- より複雑なアプリケーションで、物理的なスケールや論理的なスケールで描画を管理したい場合に有効。
コード例 (概念的)
import turtle
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("仮想座標系での描画")
# 左下(-10, -10)、右上(10, 10)の仮想座標系を設定
screen.setworldcoordinates(-10, -10, 10, 10)
t = turtle.Turtle()
t.shape("circle")
t.color("green")
t.shapesize(1) # shapesizeは仮想座標系における「相対的な」サイズになる
# 仮想座標系上で描画
t.penup()
t.goto(0, 0) # 仮想座標系の中心
t.pendown()
t.dot(2) # 仮想座標系の単位で直径2の点を打つ
# 仮想座標系上で四角形を描く
t.penup()
t.goto(-5, -5)
t.pendown()
for _ in range(4):
t.forward(10) # 仮想座標系で10単位進む
t.left(90)
t.penup()
t.goto(0, 8)
t.write("仮想座標系で描画", align="center", font=("Arial", 1, "normal")) # フォントサイズも仮想座標に合わせる
print("ウィンドウをリサイズしても、仮想座標系上の位置関係は保たれます。")
print("shapesizeやdotのサイズは、仮想座標系の相対的なサイズになります。")
screen.exitonclick()
説明
screen.setworldcoordinates(-10, -10, 10, 10)
を呼び出すことで、画面の左下が(−10,−10)、右上が(10,10)となる仮想的な座標系が設定されます。この後、t.goto(0, 0)
やt.forward(10)
といったコマンドは、この仮想座標系上での操作として解釈されます。ウィンドウがリサイズされても、この仮想座標系とピクセル座標系のマッピングが自動的に調整されるため、描画される図形の相対的な位置関係は保たれます。ただし、shapesize()
の単位が仮想座標系における比率になるため、ここでの調整は別途必要になる場合があります。