この記事では、ファイルダイアログを表示する “FileDialog” ノードの使い方について説明します。
目次
ファイルダイアログの実装方法
プロジェクトの作成
まずはプロジェクトを作成します。今回は “TestFileDialog” としました。
Mainノードの作成
まずはルートとなる Main ノードを作成します。
ここでは型を Node2D 、ノード名を “Main” としました。
FileDialogノードの作成
続けて FileDialog ノードを追加します。
FileDialog ノードは初期状態では非表示となっているため、ここをクリックして表示状態にします。
するとキャンバスにこのように表示されました。
位置とサイズを調整する
ただ表示位置とサイズがおかしい気がする…
ので、インスペクタから Window の Position を (x, y) = (64, 64)、Size を (x, y) = (640, 480) にします。
表示モードを変更する
するとこのように表示されます…
が、ファイルを開くためのファイルダイアログとは少し違う気がする (“res://” が基準になっている) ので、インスペクタからFileDialogカテゴリの項目を修正します。
- FileDialog > File Mode: Open File
- FileDialog > Access: File System
今回は単一のファイルを開くダイアログなので、このような設定としました。なお、”File Mode” の設定を変更することでダイアログの機能を変えることができます。
- Open File: 単一のファイルを開く
- Open Files: 複数のファイルを開く
- Open Folder: フォルダを開く
- Open Any: ファイルとフォルダの区別なし
- Save: ファイル保存
これでようやくそれっぽい見た目になったので、実行してみます。
ファイルダイアログっぽい挙動となりました。
ウィンドウを分離する
ここは好みの問題かもしれませんが、ウィンドウ内から移動できないのが気になる
ので、ウィンドウを分離してみます。
メニューの “プロジェクト > プロジェクト設定” を選びます。
「一般」タブを選んだ状態で「Advanced Settings」を有効にします。
そして「表示 > ウィンドウ」のカテゴリの “Subwindows > Embed Subwindows” を “オフ (チェックを外す)” にします。
この設定はサブウィンドウをメインウィンドウに埋め込むかどうかの設定で、オフにすることでサブウィンドウを別ウィンドウとして表示します。
では実行して確認すると、ファイルダイアログが別ウィンドウとして分離します。
ダイアログの表示位置が気になる場合は、インスペクタから “Window > Initial Position” を “Primary Screen Center” にすると画面中央に表示されるようになります。
フィルターを設定する
今回は 画像ファイル を読み込むダイアログを作るとします。
画像を読み込みたいので、画像以外のファイルは表示されないようにしてみます。
インスペクタから「FileDialog > Filters」をクリックします。
そして「+要素を追加」をクリックして、以下のように設定します。
- 0: *.png
- 1: *.jpg
これは拡張子が「.png」「.jpg」のものだけ表示する設定です。
では動作確認してみます。
以下のような様々な拡張子のファイルが存在するフォルダまでダイアログを移動してみます。
テスト用なのでどのようなデータでも良いですが、とりあえずテスト用データを以下に添付しておきます。
実行して確認すると、対象のフォルダの中身が「.png」「.jpg」だけ表示されるようになりました。
ファイルを読み込んで画像を表示する
ダイアログで指定した画像を読み込んで表示するようにしてみます。
“TextureRect” ノードを追加します。
そしてMainノードにスクリプトをアタッチしておきます。スクリプト名は “Main.gd” でOKです。
FileDialogノードを選択して、シグナル “file_selected” をダブルクリックして接続します。
そしてスクリプトを以下のように記述します。
extends Node2D
@onready var tex = $TextureRect
func _on_file_dialog_file_selected(path: String) -> void:
# FileAccess で読み込む.
# load() は "res://" "user://" 以外では使えない.
var file = FileAccess.open(path, FileAccess.READ)
var bytes = file.get_buffer(file.get_length())
var img = Image.new()
# 拡張子によって読み込み方法が異なる.
if path.ends_with(".png") || path.ends_with(".PNG"):
# warning-ignore:unused_variable
var error = img.load_png_from_buffer(bytes)
assert(error == Error.OK, "can't open file: %s"%path)
elif path.ends_with(".jpg") || path.ends_with(".jpeg") || path.ends_with(".JPG") || path.ends_with(".JPEG"):
# warning-ignore:unused_variable
var error = img.load_jpg_from_buffer(bytes)
assert(error == Error.OK, "can't open file: %s"%path)
else:
assert(false, "can't open file: %s"%path)
# ImageTexture経由でテクスチャにする.
var imgtex = ImageTexture.new()
# Godot4.x では create_from_image() から set_image() に変わった.
#imgtex.create_from_image(img)
imgtex.set_image(img)
# ファイル閉じる.
file.close()
# テクスチャを設定する.
tex.texture = imgtex
“res://” 以外の場所にあるテクスチャを読み込む場合には load() が使えず、特殊な方法が必要だったので少し長めのコードとなっています。
参考にしたのは以下のスレッドとGitHubのコードとなります。
実行すると指定フォルダの画像を表示できました。
ダイアログの表示をボタンで呼び出す
今の実装だと、ダイアログを閉じたら表示できなくなっているので、ダイアログ表示ボタンを実装してみます。
まずは “Button” ノードを作成します。
インスペクタの “Text” は “画像を読み込む” とします。
そしてシグナル “pressed” を作成します。
スクリプトは以下のように修正します。
extends Node2D
@onready var tex = $TextureRect
@onready var dialog = $FileDialog # ※これを追加
func _on_file_dialog_file_selected(path: String) -> void:
... (省略)
## 画像を読み込むボタンを押した
func _on_button_pressed() -> void:
# ダイアログを表示
dialog.show()
実行して動作確認をします。
完成プロジェクト
今回作成したプロジェクトファイルを添付しておきます。