メッセージダイアログ
情報、警告、エラー、質問を表示する
メッセージダイアログ
Wails は、プラットフォームに適した外観のネイティブメッセージダイアログを提供します。情報、警告、エラー、質問の各ダイアログで、タイトル、メッセージ、ボタンをカスタマイズできます。API はシンプルで、ネイティブの動作を備え、デフォルトでアクセシブルです。
ダイアログの作成
メッセージダイアログには、app.Dialogマネージャーを介してアクセスします。
app.Dialog.Info()
app.Dialog.Question()
app.Dialog.Warning()
app.Dialog.Error()すべてのメソッドは*MessageDialogを返し、メソッドチェーンを使用して設定できます。
情報ダイアログ
情報メッセージを表示します。
app.Dialog.Info().
SetTitle("Success").
SetMessage("File saved successfully!").
Show()ユースケース:
- 成功の確認
- 完了通知
- 情報メッセージ
- ステータスの更新
例 — 保存の確認:
func saveFile(app *application.App, path string, data []byte) error {
if err := os.WriteFile(path, data, 0644); err != nil {
return err
}
app.Dialog.Info().
SetTitle("File Saved").
SetMessage(fmt.Sprintf("Saved to %s", filepath.Base(path))).
Show()
return nil
}警告ダイアログ
警告を表示します。
app.Dialog.Warning().
SetTitle("Warning").
SetMessage("This action cannot be undone.").
Show()ユースケース:
- 重大ではない警告
- 非推奨化の通知
- 注意メッセージ
- 潜在的な問題
例 — ディスク容量の警告:
func checkDiskSpace(app *application.App) {
available := getDiskSpace()
if available < 100*1024*1024 { // Less than 100MB
app.Dialog.Warning().
SetTitle("Low Disk Space").
SetMessage(fmt.Sprintf("Only %d MB available.", available/(1024*1024))).
Show()
}
}エラーダイアログ
エラーを表示します。
app.Dialog.Error().
SetTitle("Error").
SetMessage("Failed to connect to server.").
Show()ユースケース:
- エラーメッセージ
- 失敗の通知
- 例外処理
- 重大な問題
例 — ネットワークエラー:
func fetchData(app *application.App, url string) ([]byte, error) {
resp, err := http.Get(url)
if err != nil {
app.Dialog.Error().
SetTitle("Network Error").
SetMessage(fmt.Sprintf("Failed to connect: %v", err)).
Show()
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}質問ダイアログ
ユーザーに質問し、ボタンのコールバックを介して応答を処理します。
dialog := app.Dialog.Question().
SetTitle("Confirm").
SetMessage("Save changes before closing?")
save := dialog.AddButton("Save")
save.OnClick(func() {
saveChanges()
})
dontSave := dialog.AddButton("Don't Save")
dontSave.OnClick(func() {
// Continue without saving
})
cancel := dialog.AddButton("Cancel")
cancel.OnClick(func() {
// Don't close
})
dialog.SetDefaultButton(save)
dialog.SetCancelButton(cancel)
dialog.Show()ユースケース:
- 操作の確認
- 「はい」または「いいえ」で答える質問
- 選択式の質問
- ユーザーによる判断
例 — 未保存の変更:
func closeDocument(app *application.App) {
if !hasUnsavedChanges() {
doClose()
return
}
dialog := app.Dialog.Question().
SetTitle("Unsaved Changes").
SetMessage("Do you want to save your changes?")
save := dialog.AddButton("Save")
save.OnClick(func() {
if saveDocument() {
doClose()
}
})
dontSave := dialog.AddButton("Don't Save")
dontSave.OnClick(func() {
doClose()
})
cancel := dialog.AddButton("Cancel")
// Cancel button has no callback - just closes the dialog
dialog.SetDefaultButton(save)
dialog.SetCancelButton(cancel)
dialog.Show()
}ダイアログのオプション
タイトルとメッセージ
dialog := app.Dialog.Info().
SetTitle("Operation Complete").
SetMessage("All files have been processed successfully.")ベストプラクティス:
- タイトル:短く、内容が分かるもの(2-5語)
- メッセージ:明確かつ具体的で、取るべき対応が分かるもの
- 専門用語を避ける:平易な言葉を使用する
ボタン
単一ボタン(情報/警告/エラー):
情報、警告、エラーの各ダイアログには、デフォルトの「OK」ボタンが表示されます。
app.Dialog.Info().
SetMessage("Done!").
Show()カスタムボタンも追加できます。
dialog := app.Dialog.Info().
SetMessage("Done!")
ok := dialog.AddButton("Got it!")
dialog.SetDefaultButton(ok)
dialog.Show()複数ボタン(質問):
AddButton()を使用してボタンを追加します。このメソッドは、設定可能な*Buttonを返します。
dialog := app.Dialog.Question().
SetMessage("Choose an action")
option1 := dialog.AddButton("Option 1")
option1.OnClick(func() {
handleOption1()
})
option2 := dialog.AddButton("Option 2")
option2.OnClick(func() {
handleOption2()
})
option3 := dialog.AddButton("Option 3")
option3.OnClick(func() {
handleOption3()
})
dialog.Show()デフォルトボタンとキャンセルボタン:
SetDefaultButton()を使用して、強調表示され、Enter キーで実行されるボタンを指定します。 SetCancelButton()を使用して、Escape キーで実行されるボタンを指定します。
dialog := app.Dialog.Question().
SetMessage("Delete file?")
deleteBtn := dialog.AddButton("Delete")
deleteBtn.OnClick(func() {
performDelete()
})
cancelBtn := dialog.AddButton("Cancel")
// No callback needed - just dismisses dialog
dialog.SetDefaultButton(cancelBtn) // Safe option as default
dialog.SetCancelButton(cancelBtn) // Escape triggers Cancel
dialog.Show()ボタンでは、流れるように記述できるSetAsDefault()メソッドとSetAsCancel()メソッドも使用できます。
dialog := app.Dialog.Question().
SetMessage("Delete file?")
dialog.AddButton("Delete").OnClick(func() {
performDelete()
})
dialog.AddButton("Cancel").SetAsDefault().SetAsCancel()
dialog.Show()ベストプラクティス:
- 1-3個のボタン:選択肢を増やしすぎてユーザーを困惑させない
- 明確なラベル:「OK」ではなく「保存」
- 安全なデフォルト:破壊的でない操作
- 順序が重要:最も選ばれる可能性が高い操作を先頭にする(「キャンセル」を除く)
カスタムアイコン
ダイアログにカスタムアイコンを設定します。
app.Dialog.Info().
SetTitle("Custom Icon Example").
SetMessage("Using a custom icon").
SetIcon(myIconBytes).
Show()ウィンドウへの関連付け
特定のウィンドウに関連付けます。
dialog := app.Dialog.Question().
SetMessage("Window-specific question").
AttachToWindow(window)
dialog.AddButton("OK")
dialog.Show()利点:
- 正しいウィンドウにダイアログが表示される
- 表示中は親ウィンドウが無効になる
- 複数ウィンドウでの UX が向上する
完全な例
破壊的な操作の確認
func deleteFiles(app *application.App, paths []string) {
// Confirm deletion
message := fmt.Sprintf("Delete %d file(s)?", len(paths))
if len(paths) == 1 {
message = fmt.Sprintf("Delete %s?", filepath.Base(paths[0]))
}
dialog := app.Dialog.Question().
SetTitle("Confirm Delete").
SetMessage(message)
deleteBtn := dialog.AddButton("Delete")
deleteBtn.OnClick(func() {
// Perform deletion
var errs []error
for _, path := range paths {
if err := os.Remove(path); err != nil {
errs = append(errs, err)
}
}
// Show result
if len(errs) > 0 {
app.Dialog.Error().
SetTitle("Delete Failed").
SetMessage(fmt.Sprintf("Failed to delete %d file(s)", len(errs))).
Show()
} else {
app.Dialog.Info().
SetTitle("Delete Complete").
SetMessage(fmt.Sprintf("Deleted %d file(s)", len(paths))).
Show()
}
})
cancelBtn := dialog.AddButton("Cancel")
dialog.SetDefaultButton(cancelBtn)
dialog.SetCancelButton(cancelBtn)
dialog.Show()
}終了の確認
func confirmQuit(app *application.App) {
dialog := app.Dialog.Question().
SetTitle("Quit").
SetMessage("You have unsaved work. Are you sure you want to quit?")
yes := dialog.AddButton("Yes")
yes.OnClick(func() {
app.Quit()
})
no := dialog.AddButton("No")
dialog.SetDefaultButton(no)
dialog.Show()
}ダウンロードオプション付きの更新ダイアログ
func showUpdateDialog(app *application.App) {
dialog := app.Dialog.Question().
SetTitle("Update").
SetMessage("A new version is available. The cancel button is selected when pressing escape.")
download := dialog.AddButton("📥 Download")
download.OnClick(func() {
app.Dialog.Info().SetMessage("Downloading...").Show()
})
cancel := dialog.AddButton("Cancel")
dialog.SetDefaultButton(download)
dialog.SetCancelButton(cancel)
dialog.Show()
}カスタムアイコン付きの質問ダイアログ
func showCustomIconQuestion(app *application.App, iconBytes []byte) {
dialog := app.Dialog.Question().
SetTitle("Custom Icon Example").
SetMessage("Using a custom icon").
SetIcon(iconBytes)
likeIt := dialog.AddButton("I like it!")
likeIt.OnClick(func() {
app.Dialog.Info().SetMessage("Thanks!").Show()
})
notKeen := dialog.AddButton("Not so keen...")
notKeen.OnClick(func() {
app.Dialog.Info().SetMessage("Too bad!").Show()
})
dialog.SetDefaultButton(likeIt)
dialog.Show()
}ベストプラクティス
✅ 推奨事項
- 具体的に記述する - 「成功」ではなく「ファイルをDocumentsに保存しました」
- 適切な種類を使用する - エラーにはError、警告にはWarningを使用する
- コンテキストを示す - 関連する詳細を含める
- 明確なボタンラベルを使用する - 「OK」ではなく「削除」を使用する
- 安全な既定値を設定する - 非破壊的な操作を既定にする
- キャンセルを処理する - ユーザーがダイアログを閉じる可能性がある
❌ 避けること
- 多用しない - 作業の流れを中断する
- 頻繁な更新には使用しない - 代わりに通知を使用する
- 漠然としたメッセージを使用しない - 「エラー」だけでは何も伝わらない
- エラーを無視しない - dialog.Show()のエラーを処理する
- 不必要にブロックしない - 非同期の代替手段を検討する
- 専門用語を使用しない - 平易な言葉を使う
プラットフォームごとの違い
macOS
- ウィンドウに関連付けるとシート形式で表示
- 標準のキーボードショートカット(キャンセルは⌘.)
- システムテーマに自動的に従う
- アクセシビリティ機能を標準搭載
Windows
- モーダルダイアログ
- TaskDialogの外観
- Escでキャンセル
- システムテーマに従う
Linux
- GTKダイアログ
- デスクトップ環境によって異なる
- デスクトップテーマに従う
- 標準のキーボードナビゲーション
次のステップ
ファイルを開く、保存する、フォルダーを選択する。
カスタムダイアログウィンドウを作成する。
作業を妨げない通知。
ノンブロッキング通信にはイベントを使用する。
ご質問がありますか? Discordで質問するか、ダイアログのサンプルを確認してください。