【Python入門】turtle.numinput()徹底解説!数値入力とエラー解決
turtle.numinput()
は、Pythonのタートルグラフィックスモジュール turtle
で提供される関数の一つで、数値の入力をユーザーに促すためのポップアップダイアログボックスを表示します。
機能と使い方
この関数は、ユーザーが指定したタイトルとプロンプトを持つ小さなウィンドウを表示し、その中に数値を入力するためのフィールドと、「OK」および「キャンセル」ボタンを提供します。ユーザーが数値を入力して「OK」をクリックすると、その数値が関数の戻り値として返されます。
基本的な構文は以下の通りです:
turtle.numinput(title, prompt, default=None, minval=None, maxval=None)
各引数の意味は以下の通りです:
maxval
(数値, オプション): 入力できる数値の最大値です。ユーザーがこれより大きい値を入力しようとすると、エラーメッセージが表示されます。minval
(数値, オプション): 入力できる数値の最小値です。ユーザーがこれより小さい値を入力しようとすると、エラーメッセージが表示されます。default
(数値, オプション): 入力フィールドにあらかじめ表示されるデフォルトの数値です。省略された場合は、何も表示されません。prompt
(文字列): 入力を促すメッセージとしてダイアログボックス内に表示される文字列です。title
(文字列): ダイアログボックスのタイトルバーに表示される文字列です。
戻り値
- ユーザーが「キャンセル」をクリックした場合、
None
が返されます。 - ユーザーが有効な数値を入力して「OK」をクリックした場合、その数値が返されます(整数または浮動小数点数)。
使用例
以下に簡単な使用例を示します。
import turtle
# タートルグラフィックスの画面設定
screen = turtle.Screen()
screen.setup(width=600, height=400)
# 数値入力を促すダイアログを表示
age = turtle.numinput("年齢入力", "あなたの年齢を入力してください:", default=25, minval=0, maxval=120)
if age is not None:
print(f"入力された年齢: {int(age)}歳")
turtle.write(f"あなたの年齢は {int(age)} 歳です。", align="center", font=("Arial", 16, "normal"))
else:
print("年齢の入力がキャンセルされました。")
turtle.write("年齢の入力がキャンセルされました。", align="center", font=("Arial", 16, "normal"))
# 画面をクリックで閉じる
screen.exitonclick()
このコードを実行すると、次のような動作になります:
- 「年齢入力」というタイトルのダイアログボックスが表示され、「あなたの年齢を入力してください:」というメッセージとともに、デフォルトで「25」が入力されたフィールドが表示されます。
- ユーザーが例えば「30」と入力して「OK」を押すと、
age
変数に30.0
が代入され、「入力された年齢: 30歳」とコンソールに出力され、タートルグラフィックスの画面にも表示されます。 - ユーザーが「キャンセル」を押すと、
age
変数にNone
が代入され、「年齢の入力がキャンセルされました。」とコンソールに出力され、画面にも表示されます。
- 入力値の制約
minval
とmaxval
を使用して、入力される数値の範囲を簡単に制限できます。 - GUIベース
テキストベースのコンソール入力(input()
など)とは異なり、グラフィカルなダイアログボックスを使用するため、ユーザーフレンドリーです。 - 簡単な数値入力
ユーザーから数値を受け取るための簡単な方法を提供します。
turtle モジュールがインポートされていない
最も基本的なエラーです。turtle.numinput()
を使用する前に、turtle
モジュールをインポートする必要があります。
エラーメッセージの例
NameError: name 'turtle' is not defined
または
AttributeError: module 'turtle' has no attribute 'numinput'
(もし from turtle import *
以外で、turtle
を適切に参照していない場合)
解決策
スクリプトの冒頭で import turtle
を追加します。
import turtle # これを忘れないでください
screen = turtle.Screen()
age = turtle.numinput("年齢入力", "あなたの年齢を入力してください:")
# ...
turtle.Screen() オブジェクトが作成されていない
numinput()
は内部でTkinterというGUIライブラリを使用しており、タートルグラフィックスの画面 (turtle.Screen()
オブジェクト) が存在しないと、ダイアログボックスを表示できません。
エラーメッセージの例
_tkinter.TclError: no display name and no $DISPLAY environment variable
または、単にダイアログが表示されない場合があります。
解決策
turtle.numinput()
を呼び出す前に、turtle.Screen()
オブジェクトを作成します。
import turtle
screen = turtle.Screen() # これを作成することが重要です
age = turtle.numinput("年齢入力", "あなたの年齢を入力してください:")
# ...
無効な引数、または引数の型が間違っている
numinput()
に渡す引数(title
, prompt
, default
, minval
, maxval
)が期待される型でない場合、エラーが発生します。
例1: タイトルやプロンプトが文字列でない場合
age = turtle.numinput(123, "あなたの年齢を入力してください:") # titleが数値
# TypeError: numinput() argument 1 must be str, not int
例2: default, minval, maxval が数値でない場合
age = turtle.numinput("年齢入力", "あなたの年齢を入力してください:", default="二十五") # defaultが文字列
# TclError: expected floating-point number but got "二十五"
解決策
各引数が正しい型(title
と prompt
は文字列、default
, minval
, maxval
は数値)であることを確認してください。
numinput() が None を返す場合の処理忘れ
ユーザーが numinput()
ダイアログで「キャンセル」ボタンをクリックした場合、関数は None
を返します。この None
を適切に処理しないと、後続の処理でエラーが発生する可能性があります。
エラーの例
age
が None
の状態で、それを数値として扱おうとすると TypeError
が発生します。
import turtle
screen = turtle.Screen()
age = turtle.numinput("年齢入力", "あなたの年齢を入力してください:")
# ここでユーザーがキャンセルすると age は None になる
# None に対して数値演算を行おうとするとエラーになる
if age > 18: # TypeError: '>' not supported between instances of 'NoneType' and 'int'
print("成人です")
解決策
numinput()
の戻り値が None
でないかを確認してから、その値を使用するようにします。
import turtle
screen = turtle.Screen()
age = turtle.numinput("年齢入力", "あなたの年齢を入力してください:")
if age is not None: # None でないことを確認
print(f"入力された年齢: {int(age)}歳")
if age >= 18:
print("成人です")
else:
print("未成年です")
else:
print("入力がキャンセルされました。")
numinput() が他のイベントハンドラと競合する場合
まれなケースですが、turtle.numinput()
を使用しているときに、screen.onkeypress()
や screen.onclick()
のような他のイベントハンドラが期待通りに動作しないことがあります。これは、numinput()
が表示されている間、メインイベントループがブロックされるため、他のイベントが処理されないことに起因する可能性があります。
問題の症状
numinput()
が表示されている間や、その呼び出し後に、キー入力やマウスクリックが検出されない。
解決策 (状況による)
- より高度なGUIライブラリの検討
複雑なインタラクションが必要な場合は、turtle
モジュールが提供する簡易的なGUI機能ではなく、直接tkinter
やPyQt
などのより本格的なGUIライブラリを使用することを検討する方が良い場合もあります。 - メインイベントループのブロック
numinput()
はモーダルダイアログ(ユーザーが操作するまで他の操作ができないダイアログ)なので、その特性を理解してプログラムの流れを設計する必要があります。 - numinput() の呼び出し順序
numinput()
を呼び出す前に、必要なイベントハンドラを設定してみてください。場合によっては、numinput()
が処理された後に、イベントハンドラを再設定する必要があるかもしれません。
turtle.numinput()
は数値を返すことを前提としていますが、turtle.textinput()
と混同して、文字列として扱おうとすると意図しない結果になることがあります。また、ユーザーが数値ではないものを入力しようとした場合、numinput()
は自動的にエラーメッセージを表示し、再入力を促します(デフォルトで)。
解決策
numinput()
の戻り値は自動的に数値型(int
または float
)になるため、通常は明示的な型変換(int()
や float()
)は不要です。ただし、特定の整数として扱いたい場合は int()
で変換できます。
例1:基本的な数値入力と結果の表示
最も基本的な使い方です。ユーザーに年齢を入力してもらい、それを画面に表示します。
import turtle
# 画面とタートルの設定
screen = turtle.Screen()
screen.setup(width=600, height=400) # 画面サイズを設定
screen.title("年齢入力プログラム")
my_turtle = turtle.Turtle()
my_turtle.hideturtle() # タートル自身は非表示にする
my_turtle.penup() # 線を描かないようにペンを上げる
# numinput() で数値入力を受け付ける
# 引数: (タイトル, プロンプトメッセージ, デフォルト値, 最小値, 最大値)
age = turtle.numinput("年齢の入力", "あなたの年齢を入力してください:", default=20, minval=0, maxval=120)
# 入力がキャンセルされたか、有効な数値が入力されたかをチェック
if age is not None:
# 整数に変換して表示
my_turtle.goto(0, 50)
my_turtle.write(f"入力された年齢: {int(age)}歳", align="center", font=("Arial", 24, "bold"))
# 年齢に応じたメッセージ
my_turtle.goto(0, 0)
if age >= 20:
my_turtle.write("あなたは成人です。", align="center", font=("Arial", 18, "normal"))
else:
my_turtle.write("あなたは未成年です。", align="center", font=("Arial", 18, "normal"))
else:
my_turtle.goto(0, 0)
my_turtle.write("入力がキャンセルされました。", align="center", font=("Arial", 20, "normal"))
# 画面をクリックするとプログラムが終了
screen.exitonclick()
解説
my_turtle.write()
を使って、タートルグラフィックスの画面上にテキストを表示しています。if age is not None:
で、ユーザーが「キャンセル」をクリックした場合の処理を分けています。turtle.numinput()
で年齢の入力を促します。default
,minval
,maxval
を指定して、入力の利便性と制約を設けています。my_turtle.hideturtle()
とmy_turtle.penup()
は、メッセージ表示のためにタートルそのものは見せず、線も引かないようにするための設定です。screen.setup()
やscreen.title()
でウィンドウの設定をしています。
例2:numinput()
を使って図形のサイズを動的に変更する
ユーザーからの入力に基づいて、描画する図形のサイズを変更する例です。
import turtle
screen = turtle.Screen()
screen.setup(width=600, height=600)
screen.title("図形のサイズ変更")
t = turtle.Turtle()
t.speed(0) # 描画速度を最速に
# ユーザーに辺の長さを入力してもらう
side_length = turtle.numinput(
"正方形の描画",
"正方形の1辺の長さを入力してください (50-200):",
default=100,
minval=50,
maxval=200
)
if side_length is not None:
side_length = int(side_length) # 整数に変換
t.penup()
t.goto(-side_length / 2, -side_length / 2) # 中心に描画されるように開始位置を調整
t.pendown()
t.color("blue")
t.pensize(3)
# 正方形を描画
for _ in range(4):
t.forward(side_length)
t.left(90)
t.penup()
t.goto(0, side_length / 2 + 20)
t.write(f"1辺 {side_length} の正方形を描画しました。", align="center", font=("Arial", 16, "normal"))
else:
t.write("入力がキャンセルされました。", align="center", font=("Arial", 20, "normal"))
screen.exitonclick()
解説
int(side_length)
で入力された数値を整数に変換し、辺の長さに使用しています。- 入力された
side_length
に基づいて、タートルを移動させ、指定されたサイズの正方形を描画しています。 numinput()
で正方形の辺の長さを入力してもらいます。ここでもminval
とmaxval
で適切な範囲を指定しています。
複数の numinput()
を連続して使用し、描画する線の色(RGB値)と太さをユーザーに選んでもらう例です。
import turtle
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("色の変更と線の描画")
t = turtle.Turtle()
t.speed(0)
# RGB値の入力を促す
red = turtle.numinput("色の選択 (赤)", "赤成分を入力してください (0-255):", default=0, minval=0, maxval=255)
green = turtle.numinput("色の選択 (緑)", "緑成分を入力してください (0-255):", default=0, minval=0, maxval=255)
blue = turtle.numinput("色の選択 (青)", "青成分を入力してください (0-255):", default=0, minval=0, maxval=255)
# 線の太さの入力を促す
pen_size = turtle.numinput("線の太さ", "線の太さを入力してください (1-10):", default=2, minval=1, maxval=10)
# いずれかの入力がキャンセルされた場合は終了
if red is None or green is None or blue is None or pen_size is None:
t.write("入力がキャンセルされました。", align="center", font=("Arial", 20, "normal"))
else:
# RGB値を整数に変換し、タートルの色を設定
# screen.colormode(255) を設定することで、0-255のRGB値を使用できます
screen.colormode(255)
t.color(int(red), int(green), int(blue))
# 線の太さを設定
t.pensize(int(pen_size))
# 線を描画
t.penup()
t.goto(-200, 0)
t.pendown()
t.forward(400) # 横一直線に描画
t.penup()
t.goto(0, 50)
t.write(f"色: RGB({int(red)},{int(green)},{int(blue)}), 太さ: {int(pen_size)}", align="center", font=("Arial", 14, "normal"))
screen.exitonclick()
- 入力された値を使って、描画する線の色と太さを動的に設定しています。
screen.colormode(255)
を設定することで、color()
メソッドでRGB値を0から255の範囲で指定できるようになります(デフォルトは0.0から1.0)。- 複数の
numinput()
を連続して呼び出し、それぞれ異なる情報を取得しています。
input() 関数 (コンソール入力)
これはPythonの最も基本的な入力方法で、プログラムを実行している**コンソール(ターミナル)**からユーザーにテキスト入力を求めます。数値入力を受け取る場合でも、最初は文字列として受け取るため、型変換が必要です。
特徴
- 型変換が必要
受け取る値は常に文字列なので、数値として扱いたい場合はint()
やfloat()
で変換する必要があります。 - GUIなし
グラフィカルなダイアログは表示されず、すべてコンソール上で行われます。 - シンプル
非常に簡単に実装できます。
使用例
import turtle
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("コンソール入力の例")
# コンソールから年齢を入力
# input() は文字列を返すので、int() で整数に変換
try:
age_str = input("あなたの年齢を入力してください: ")
age = int(age_str)
# タートルグラフィックス画面に表示
t = turtle.Turtle()
t.hideturtle()
t.penup()
t.goto(0, 0)
t.write(f"入力された年齢: {age}歳", align="center", font=("Arial", 20, "normal"))
except ValueError:
# 数値以外の入力があった場合の処理
t = turtle.Turtle()
t.hideturtle()
t.penup()
t.goto(0, 0)
t.write("無効な入力です。数値を入力してください。", align="center", font=("Arial", 20, "normal"))
except Exception as e:
t = turtle.Turtle()
t.hideturtle()
t.penup()
t.goto(0, 0)
t.write(f"エラーが発生しました: {e}", align="center", font=("Arial", 20, "normal"))
screen.exitonclick()
利点
- GUI環境がない場合でも使える。
- 最も手軽。
欠点
- 無効な入力(数値以外など)に対して、自分でエラーハンドリングを実装する必要がある。
- グラフィカルなユーザーインターフェースがない。
Pythonの標準ライブラリであるTkinterは、GUIアプリケーションを構築するためのツールキットです。turtle
モジュールも内部でTkinterを使用しており、より高度なダイアログや入力フォームを作成したい場合に直接Tkinterを使うことができます。
特に、tkinter.simpledialog
モジュールには askinteger()
や askfloat()
といった便利な関数があります。
特徴
- エラーハンドリング内蔵
numinput()
と同様に、無効な入力に対して自動的に警告を表示します。 - より柔軟
ダイアログのタイトル、メッセージ、初期値、最小値、最大値などを細かく設定できます。 - GUIベース
グラフィカルなダイアログボックスを表示します。
使用例 (Tkinterの simpledialog)
import tkinter as tk
from tkinter import simpledialog
import turtle
# Tkinterのルートウィンドウは通常必要ですが、
# simpledialogを使うだけであれば表示しないことも可能
root = tk.Tk()
root.withdraw() # ルートウィンドウを表示しない
# タートルグラフィックスの設定
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("Tkinter simpledialogの例")
t = turtle.Turtle()
t.hideturtle()
t.penup()
# askinteger() で整数入力を受け付ける
# numinput() とほぼ同じ使い方ができます
try:
number = simpledialog.askinteger(
"数値の入力",
"好きな整数を入力してください:",
initialvalue=50,
minvalue=0,
maxvalue=100
)
if number is not None:
t.goto(0, 0)
t.write(f"入力された整数: {number}", align="center", font=("Arial", 20, "normal"))
else:
t.goto(0, 0)
t.write("入力がキャンセルされました。", align="center", font=("Arial", 20, "normal"))
except Exception as e:
t.goto(0, 0)
t.write(f"エラーが発生しました: {e}", align="center", font=("Arial", 20, "normal"))
screen.exitonclick()
利点
- より複雑なGUIが必要になった場合、Tkinterに移行しやすい。
- Pythonの標準ライブラリなので、追加インストール不要。
turtle.numinput()
と同様のGUIダイアログを提供し、より細かい制御が可能。
欠点
- Tkinterの見た目がやや古く感じる場合がある。
turtle
モジュールと併用する場合、root = tk.Tk(); root.withdraw()
のようなTkinterの初期化が必要になる場合がある。
よりモダンで高機能なGUIを構築したい場合、サードパーティ製のGUIライブラリを検討することができます。これらは非常に強力ですが、インストールと学習のコストがかかります。
- PySimpleGUI
Tkinter, PyQt, WxPython, Remi (Web) のいずれかをバックエンドとして使用できる、GUI開発を簡素化するためのライブラリ。簡単にGUIを作成したい場合に非常に便利です。 - Kivy
マルチタッチアプリケーション開発に特化したライブラリ。クロスプラットフォーム対応で、モバイルアプリ開発にも使われます。 - PyQt / PySide
QtフレームワークのPythonバインディング。非常に高機能で美しいGUIアプリケーションを開発できます。複雑な入力フォームやカスタマイズされたダイアログボックスの作成に適しています。
特徴
- 学習コスト
ある程度の学習が必要になります。 - モダンな見た目
最新のOSデザインに合わせたGUIを作成可能です。 - 高機能・高カスタマイズ性
非常にリッチなUIを作成できます。
使用例 (PySimpleGUIの概念)
# PySimpleGUI はインストールが必要です: pip install PySimpleGUI
import PySimpleGUI as sg
import turtle
# タートルグラフィックスの設定
screen = turtle.Screen()
screen.setup(width=600, height=400)
screen.title("PySimpleGUIの例")
t = turtle.Turtle()
t.hideturtle()
t.penup()
# PySimpleGUIのレイアウトを定義
layout = [
[sg.Text("好きな数字を入力してください:")],
[sg.InputText(key='-INPUT-')],
[sg.Button('OK'), sg.Button('キャンセル')]
]
# ウィンドウを作成
window = sg.Window("数値入力", layout)
# イベントループ
event, values = window.read()
window.close()
if event == 'OK':
try:
number_str = values['-INPUT-']
number = int(number_str)
t.goto(0, 0)
t.write(f"入力された数字: {number}", align="center", font=("Arial", 20, "normal"))
except ValueError:
t.goto(0, 0)
t.write("無効な入力です。整数を入力してください。", align="center", font=("Arial", 20, "normal"))
else: # キャンセルまたはウィンドウが閉じられた場合
t.goto(0, 0)
t.write("入力がキャンセルされました。", align="center", font=("Arial", 20, "normal"))
screen.exitonclick()
利点
- PySimpleGUIのように、簡単にGUIを構築できるライブラリもある。
- 見た目の良い、複雑なGUIを開発できる。
- 学習コストが
turtle.numinput()
やinput()
より高い。 - 外部ライブラリのインストールが必要。