質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Q&A

解決済

2回答

3329閲覧

Python3 Tkinter ダイアログ表示したい

person

総合スコア223

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

0グッド

0クリップ

投稿2020/07/01 10:29

messageboxを表示したいのですが、フォントの大きさなどを変えられないということなどから、自作することにしました。

とりあえず作ってみたのが下のようになるのですが、
標準のmessageboxだとOK・キャンセル、はい・いいえなどを選ぶと
戻り値としてTrue・False、yes・noなどを得ることができますが、
下のように作ったときに戻り値をうまく設定できません。

実現することは可能でしょうか?

Python

1import tkinter as tk 2import tkinter.ttk as ttk 3 4def my_ask(e): 5 6 def ok_pushed(e): 7 sub.grab_release() 8 sub.destroy() 9 print("ok") 10 11 def cancel_pushed(e): 12 cancel() 13 14 def cancel(): 15 sub.grab_release() 16 sub.destroy() 17 print("cancel") 18 19 sub = tk.Toplevel() 20 sub.attributes("-topmost", True) 21 sub.resizable(0, 0) 22 sub.transient(win) 23 sub.grab_set() 24 25 sub.grid_rowconfigure(0, weight=1) 26 sub.grid_columnconfigure(0, weight=1) 27 28 f_msg = tk.Frame(sub) 29 f_msg.grid(row=0, column=0, sticky="nsew") 30 f_btn = tk.Frame(sub) 31 f_btn.grid(row=1, column=0, sticky="nsew") 32 33 f_msg.grid_rowconfigure(0, weight=1) 34 f_msg.grid_columnconfigure(0, weight=1) 35 msg = "Are you okay?" 36 l = tk.Label(f_msg, text=msg, font=("",15)) 37 l.grid(row=0, column=0, sticky="nsew", pady=20) 38 39 f_btn.grid_rowconfigure(0, weight=1) 40 f_btn.grid_columnconfigure((0,1), weight=1) 41 s = ttk.Style() 42 s.configure("TButton", font=("",15)) # TButtonは print(ttk.Button().winfo_class()) で確認 43 b_ok = ttk.Button(f_btn, text="ok", width=10, style="TButton") 44 b_ok.grid(row=0, column=0, sticky="nsew", padx=10, pady=20) 45 b_cancel = ttk.Button(f_btn, text="cancel", width=10, style="TButton") 46 b_cancel.grid(row=0, column=1, sticky="nsew", padx=10, pady=20) 47 48 b_ok.bind("<ButtonRelease>", ok_pushed) 49 b_cancel.bind("<ButtonRelease>", cancel_pushed) 50 51 sub.protocol("WM_DELETE_WINDOW", cancel) 52 53win = tk.Tk() 54 55b = tk.Button(win, text="toplevel()", width=10) 56b.grid() 57 58b.bind("<ButtonRelease>", my_ask) 59 60win.mainloop()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ジャストアイデアです。

wait_window() にてダイアログが閉じられるまで待機し、待機解除後に結果が格納された変数を参照するというのはどうでしょうか。

Python

1import tkinter as tk 2import tkinter.ttk as ttk 3 4def my_ask(e): 5 result = False 6 7 def ok_pushed(e): 8 nonlocal result 9 sub.grab_release() 10 sub.destroy() 11 result = True 12 13 def cancel_pushed(e): 14 cancel() 15 16 def cancel(): 17 nonlocal result 18 sub.grab_release() 19 sub.destroy() 20 print("cancel") 21 result = False 22 23 sub = tk.Toplevel() 24 sub.attributes("-topmost", True) 25 sub.resizable(0, 0) 26 sub.transient(win) 27 sub.grab_set() 28 29 sub.grid_rowconfigure(0, weight=1) 30 sub.grid_columnconfigure(0, weight=1) 31 32 f_msg = tk.Frame(sub) 33 f_msg.grid(row=0, column=0, sticky="nsew") 34 f_btn = tk.Frame(sub) 35 f_btn.grid(row=1, column=0, sticky="nsew") 36 37 f_msg.grid_rowconfigure(0, weight=1) 38 f_msg.grid_columnconfigure(0, weight=1) 39 msg = "Are you okay?" 40 l = tk.Label(f_msg, text=msg, font=("",15)) 41 l.grid(row=0, column=0, sticky="nsew", pady=20) 42 43 f_btn.grid_rowconfigure(0, weight=1) 44 f_btn.grid_columnconfigure((0,1), weight=1) 45 s = ttk.Style() 46 s.configure("TButton", font=("",15)) # TButtonは print(ttk.Button().winfo_class()) で確認 47 b_ok = ttk.Button(f_btn, text="ok", width=10, style="TButton") 48 b_ok.grid(row=0, column=0, sticky="nsew", padx=10, pady=20) 49 b_cancel = ttk.Button(f_btn, text="cancel", width=10, style="TButton") 50 b_cancel.grid(row=0, column=1, sticky="nsew", padx=10, pady=20) 51 52 b_ok.bind("<ButtonRelease>", ok_pushed) 53 b_cancel.bind("<ButtonRelease>", cancel_pushed) 54 55 sub.protocol("WM_DELETE_WINDOW", cancel) 56 57 # Dialogが閉じられるまで待機 58 win.wait_window(sub) 59 60 # 結果を表示 61 print(result) 62 63 64win = tk.Tk() 65 66b = tk.Button(win, text="toplevel()", width=10) 67b.grid() 68 69b.bind("<ButtonRelease>", my_ask) 70 71win.mainloop()

投稿2020/07/01 11:19

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

別アプローチですが
simpledialog のクラスを利用して2通り

simpledialog.Dialog をカスタマイズする

ドキュメントに書かれている方法で、
body, buttonbox をオーバーライドして独自のウィジェットを配置します。

イメージ説明

python

1#!/usr/bin/env python3.8 2 3""" 4 5https://docs.python.org/ja/3.9/library/dialog.html#module-tkinter.simpledialog 6 7class tkinter.simpledialog.Dialog(parent, title=None) 8 The base class for custom dialogs. 9 10 body(master) 11 Override to construct the dialog's interface and return the widget that should have initial focus. 12 13 buttonbox() 14 Default behaviour adds OK and Cancel buttons. Override for custom button layouts. 15 16""" 17 18import tkinter as tk 19from tkinter import ttk 20from tkinter.simpledialog import Dialog 21from functools import partial 22 23 24MyFrame = partial(ttk.Frame, style="MyDialog.TFrame") 25MyLabel = partial(ttk.Label, style="MyDialog.TLabel") 26MyButton = partial(ttk.Button, style="MyDialog.TButton") 27 28 29class AskYesNoDialog(Dialog): 30 31 def __init__(self, parent=None, title="", message=""): 32 33 if not parent: 34 parent = tkinter._default_root 35 36 self._message = message 37 38 Dialog.__init__(self, parent, title) 39 40 41 def body(self, master): 42 MyLabel(master, text=self._message).pack() 43 44 def buttonbox(self): 45 frame = MyFrame(self) 46 frame.pack() 47 48 w = MyButton(frame, text="OK", command=self.ok, default=tk.ACTIVE) 49 w.pack(side=tk.LEFT, padx=5, pady=5) 50 51 w = MyButton(frame, text="Cancel", command=self.cancel) 52 w.pack(side=tk.LEFT, padx=5, pady=5) 53 54 def validate(self): 55 # XXX: 56 self.result = True 57 return 1 58 59 60# see also tkinter.messagebox.askyesno 61def askyesno(title, message=None, parent=None): 62 dialog = AskYesNoDialog(parent, title, message) 63 return dialog.result 64 65 66if __name__ == "__main__": 67 root = tk.Tk() 68 root.withdraw() 69 70 font = ("", 30) 71 style = ttk.Style() 72 style.configure("MyDialog.TLabel", font=font) 73 style.configure("MyDialog.TButton", font=font) 74 75 result = askyesno("Question", "Are you OK?", parent=root) 76 print("RESULT>", result)

simpledialog.SimpleDialog をカスタマイズして使う

少しトリッキーな方法です。
Pythonでは動的に名前を解決するので、
モジュールに読み込まれている tkinterのウィジェット を ttk のもので上書き可能です。
(但し、ttkウィジェットのクラスは完全互換ではない為、引数が違ったりするものはうまく動きません。)

注意点: SimpleDialogクラスはドキュメントに書かれてない為、内部クラスかもしれません。
(メソッドの引数等、互換性の保証はなく、予告なく変更される可能性がある)

イメージ説明

python

1#!/usr/bin/env python3.8 2 3""" 4SimpleDialog で ttk を使う方法 + non-ttk のフォント変更 5""" 6 7 8import tkinter as tk 9from tkinter import ttk, simpledialog 10from functools import partial 11 12## patch simpledialog.* tk widget -> ttk's widget (with custom style name) 13simpledialog.Frame = partial(ttk.Frame, style="MyDialog.TFrame") 14simpledialog.Label = partial(ttk.Label, style="MyDialog.TLabel") 15simpledialog.Button = partial(ttk.Button, style="MyDialog.TButton") 16 17 18def askyesno(title="", message="", parent=None): 19 buttons = ["OK", "Cancel"] 20 dialog = simpledialog.SimpleDialog( 21 master=parent, 22 title=title, 23 text=message, 24 buttons=buttons) 25 return buttons[dialog.go()] 26 27 28if __name__ == "__main__": 29 root = tk.Tk() 30 31 font = ("", 30) 32 style = ttk.Style() 33 style.configure("MyDialog.TLabel", font=font) 34 style.configure("MyDialog.TButton", font=font) 35 36 def clicked(): 37 # change tkinter.Message font (non-ttk widget) 38 root.option_add("*Message.font", "Helvetica 30") 39 40 result = askyesno("Question", "Are you OK?", parent=root) 41 print("RESULT>", result) 42 43 root.option_clear() 44 45 46 ttk.Button(root, text="ask", command=clicked).pack() 47 48 root.mainloop()

投稿2020/07/01 16:42

編集2020/07/01 16:45
teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問