この記事では電卓風の数値入力UIの実装方法を紹介します。
目次
電卓風の数値入力UIの実装方法
素材データのダウンロード
今回は日本語フォントを使用するのでこちらのデータをダウンロードしてプロジェクトに追加しておきます。
テーマリソースの作成
日本語フォントを使用するためにテーマリソースを作成します。
ファイルシステムを右クリックして「新規リソース」を選び、Themeリソースを作成します。
テーマリソースのファイル名は何でもよいですが、ここでは「new_theme.tres」としておきます。
作成した “new_theme.tres” をダブルクリックして、インスペクターから「Theme > Default Font > [空]」をクリックして「新規 DynamicFont」を選びます。
作成した「DynamicFont」をクリックするとフォント設定が表示されるので「Font > Font Data > [空]」をクリックして「読み込み」を選びます。
日本語フォント “mplus-1c-regular.ttf” を読み込みます。
フォントサイスを少し大きくしたいので、「Settings > Size」の値を「24」に変更しておきます。
テーマビューの「保存」をクリックして変更を保存しておきます。
シーンの作成
今回はUIなので、Controlノード (ユーザーインターフェース) を作成します。
名前は「Main」に変更しておきます。
UIノードのレイアウト
各UIノードを作成する前にレイアウトの完成図を示しておきます。
外枠に「VBoxContainer」を作成し、その中に、「Label」「GridContainer」「Button」の順で配置します。
そして「GridContainer」の中には、数字入力の「Button」を配置します。
VBoxContainerの作成
まずは VBoxContainer を作成します。このノードは子となるノードを縦方向に並べるコンテナとなります。
Labelの作成
次に入力した数値を表示する Label ノードを作成します。
そしてインスペクターから「Control > Theme > Theme > [空]」をクリックして「読み込み」を選びます。
先程作成したテーマ “new_theme.tres” を開きます。
GridContainer の作成
ボタンをグリッド(格子)上に並べるために GridContainerを作成します。
そしてインスペクターから「GridContainer > Columns」の値を「3」に設定します。
これで横のサイズが「3つ」のグリッドコンテナとなります。
数字ボタンの配置
Buttonノードを配置していきます。
電卓のような配置とするので、まずは一段目に「7」「8」「9」と並ぶようにします。
GirdContainerの下にButtonノードを作成し、ノード名は「Button7」にリネームします。
そしてインスペクターから「Control > Theme > Theme > [空]」をクリックして、「読み込み」を選びます。
“new_theme.tres” を開きます。
テーマを設定したら「Button > Text」に「7」を指定します。
このButtonノードをもとに各数字ボタンを作成するために複製を行います。
複製するには「Button7」ノードを選択した状態で「Ctrl+D (macOSの場合は Cmd+D」でボタンを複製します。
10個ほど複製して、以下のようにリネームします。
- Button8: Text「8」
- Button9: Text「9」
- Button4: Text「4」
- Button5: Text「5」
- Button6: Text「6」
- Button1: Text「1」
- Button2: Text「2」
- Button3: Text「3」
- Button0: Text「0」
- ButtonClear: Text「C」
ここまでできたら Mainノードを選んでスクリプトを作成し、
スクリプトには以下のように記述します。
extends Control
# 入力可能な最大桁数
const MAX_DIGIT = 4 # 最大4文字まで
# 入力した数値を表示するラベル
onready var label = $VBoxContainer/Label
func _ready() -> void:
for i in range(10):
# 0〜9の数値ボタンのノードを取得する
var name = "VBoxContainer/GridContainer/Button%d"%i
var btn:Button = get_node(name)
# シグナルを接続する
# ・第1引数: シグナル名
# ・第2引数: 接続する関数を持つインスタンス
# ・第3引数: 接続する関数名
# ・第4引数: 関数に渡すパラメータ
btn.connect("pressed", self, "_on_NumberButton_pressed", [i])
func _on_NumberButton_pressed(num) -> void:
# 数値ボタンの入力
if label.text.length() < MAX_DIGIT:
# 最大桁数より小されば文字を追加
label.text += "%d"%num
0〜9の数値ボタンを get_node() で取得し、connect() でボタンにシグナルを接続しています。”connect()” 関数の説明は以下のとおりです
・第1引数: シグナル名
・第2引数: 接続する関数を持つインスタンス
・第3引数: 接続する関数名
・第4引数: 関数に渡すパラメータ(引数)
“pressed” シグナル (ボタンを押した) を受け取ったら、”_on_NumberButton_pressed()” を呼び出し、引数はボタンの数字となります。
では実行して、数字が4桁まで指定できることを確認します。
入力した数値のクリアボタンの実装
「ButtonClear」ノードを選択して、シグナル「pressed」を作成します。
接続した関数は以下のように記述します。
func _on_ButtonClear_pressed() -> void:
# 入力文字を消す
label.text = ""
実行して入力した数値が消えることを確認します。
問題文と正解判定の実装
最後に問題文と正解判定の実装を行います。
まずはボタンを複製(右クリックして「複製」または Ctrl+Dなど)します。
そしてノード名を「ButtonEnter」にリネームします
これを確定ボタンとします。
GridContainerと同じ階層の下に配置したいので、以下の手順でうまく移動させます。
- ButtonEnter を GridContainer の「上」に移動させる (Ctrl+↑キーで移動させてドラッグ&ドロップする)
- GridContainer を ButtonEnter の「上」に移動させる
いきなり下に移動させることはできないようなので、”ButtonEnter” を上に移動させてから “GridContainer” をその上に移動させることで “ButtonEnter” を “GridContainer” と同階層の下に移動させることができます。
そして移動させた “ButtonEnter” ノードのインスペクタから Text を「決定」とします。
これでUIのレイアウトが電卓っぽい見た目となりました。
次に Mainノードを選択して、その直下に Labelノードを2つ作成します。
- Label2: 問題文テキスト
- Label3: 正解判定結果テキスト
このテキストは数値入力とは別の部分に配置したいので、ルートノードに直接ぶら下げるようにしました
そして、それぞれにテーマを設定 (Control > Theme > Theme > [空] をクリックして「読み込み」で “new_theme.tres” を読み込む) しておき、日本語を表示できるようにしておきます。
“Label2″ の Textには「ヒント:チョコレート」、”Label3” には「4桁の数値を入力」と指定します。
このようなレイアウトとなりました。
なお、数値入力ノードの “VBoxContainer” をマウス操作で移動させる場合、選択モードで移動させると子ノードが選択されて移動させにくいため「移動モード」を選ぶと移動させやすいです。
各種ボタンのシグナル設定
“ButtonEnter” に “pressed” シグナルを接続します。
シグナル関数は以下のように記述します。
onready var label3 = $Label3 # 正解判定結果テキスト
...
func _on_ButtonEnter_pressed() -> void:
# 正解判定
if label.text == "0214":
label3.text = "正解!"
else:
label3.text = "不正解"
“Label3″ に正解判定のテキストを設定したいので、”onready” で “label3” 変数に格納しておきます。
答えは、バレンタインデーの日付 “0214” となります。
それと シグナル関数 “_on_ButtonClear_pressed()” (消去ボタン) を以下のように修正しておきます。(正解判定のテキストも消しておく)
func _on_ButtonClear_pressed() -> void:
# 入力文字を消す
label.text = ""
# 正解判定の文字も消しておきます
label3.text = ""
では、実行して動作を確認します。
完成プロジェクト
今回作成したプロジェクトを添付しておきます。
参考
今回の記事を書くにあたって以下の記事を参考にしました
シグナルの設定方法について詳しく書かれているので、参考になります。