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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Tkinter

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

6626閲覧

【Python】【Tkinter】サブウィンドウでMessageboxが表示されると、トップレベルウィンドウが前に出てきてしまう

mintiamegahard

総合スコア8

Tkinter

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/03/23 04:59

###前提

・Comboboxを用いて日付(年/月/日)を選択し、存在しない日付(例:2020年2月31日)の時にmessagebox(showerror)を表示するプログラムを作成した。
・messageboxは、年/月/日の3つすべてのプルダウンを選択してから表示される。

OS:Windows 10
Pythonバージョン:3.5.4(64bit)
開発環境:Pycharm

###発生している問題・エラーメッセージ

タイトルの通り、存在しない日付を選択した時、messageboxが表示されるのと同時にトップレベルウィンドウが前に出てきてしまいます。

エラーメッセージ:特になし

###実現したい事

messageboxをサブウィンドウ上のままで表示できるようにしたい。

###該当のソースコード

Python

1import tkinter as tk 2import tkinter.ttk as ttk 3import datetime 4from tkinter import messagebox as mb 5 6# メインウィンドウの作成 7root = tk.Tk() 8root.title('Main') 9 10# サブウィンドウを表示したときにメインウィンドウを使用不可にする 11sd_win = None 12 13 14# サブウィンドウの生成 15def select_date(): 16 global sd_win 17 if sd_win is None or not sd_win.winfo_exists(): 18 sd_win = tk.Toplevel() 19 sd_win.title('Select Date') 20 21 label_date = tk.Label(sd_win, text=u'日付') 22 label_date.grid(row=2, column=0, padx=20, pady=10) 23 label_year = tk.Label(sd_win, text=u'年') 24 label_year.grid(row=2, column=4, padx=1) 25 label_month = tk.Label(sd_win, text=u'月') 26 label_month.grid(row=2, column=6, padx=1) 27 label_day = tk.Label(sd_win, text=u'日') 28 label_day.grid(row=2, column=8, padx=1) 29 30 # コンボボックスの作成 31 32 # 日付 33 # 年 34 year_cb = ttk.Combobox(sd_win, width=6, justify=tk.RIGHT) 35 year_cb.set('') 36 year_cb['values'] = tuple(range(1990, 2023)) 37 year_cb.grid(row=2, column=3, sticky=tk.E) 38 39 # 月 40 month_cb = ttk.Combobox(sd_win, width=3, justify=tk.RIGHT) 41 month_cb.set('') 42 month_cb['values'] = tuple(range(1, 13)) 43 month_cb.grid(row=2, column=5, sticky=tk.E) 44 45 # 日 46 day_cb = ttk.Combobox(sd_win, width=3, justify=tk.RIGHT) 47 day_cb.set('') 48 day_cb['values'] = tuple(range(1, 32)) 49 day_cb.grid(row=2, column=7, sticky=tk.E) 50 51 # 日付の確認 52 def check_date(y, m, d): 53 try: 54 # y, m, dすべて入力した時のみ 55 datetime.date(int(y), int(m), int(d)) 56 return True 57 except Exception: 58 return False 59 60 def get_item(event): 61 if not year_cb.get() or not month_cb.get() or not day_cb.get() \ 62 or check_date(year_cb.get(), month_cb.get(), day_cb.get()): 63 pass 64 elif Exception: 65 mb.showerror('警告', '日付選択のエラー') #サブウィンドウ上で表示されるようにしたい。 66 67 year_cb.bind('<<ComboboxSelected>>', get_item) 68 year_cb.bind('<Return>', get_item) 69 month_cb.bind('<<ComboboxSelected>>', get_item) 70 month_cb.bind('<Return>', get_item) 71 day_cb.bind('<<ComboboxSelected>>', get_item) 72 day_cb.bind('<Return>', get_item) 73 74 75# [日付選択]ボタン 76button_date_select = tk.Button(text='日付選択', command=select_date) 77button_date_select.grid() 78 79# 表示 80root.mainloop() 81

ご回答よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

メッセージボックスは、表示中は親ウィンドウを操作させないモーダルダイアログですが、
親を指定しない場合、rootに対してのモーダルになります。

メインウィンドウ root -> サブウィンドウ sd_win -> メッセージボックス showerror

と、今回のケースでは、間にサブウィンドウがあるため、
意図しない挙動になっているのだと思われます。
これは、親ウィンドウを知らせることで解消できます。

python

1mb.showerror('警告', '日付選択のエラー', parent=sd_win) #サブウィンドウ上で表示されるようにしたい。

尚、上の変更でshowerrorを表示中サブウィンドウの操作はできなくなりますが、
メインウィンドウは操作可能のままなので、これも抑止したい場合は、
サブウィンドウもモーダルにします。

python

1sd_win.grab_set()

投稿2020/03/23 06:05

teamikl

総合スコア8760

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

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

mintiamegahard

2020/03/23 08:15

termikl様、前回に引き続きありがとうございます。教えていただいた内容を試したところ、無事実行できました!messagebox内の()内にも変数?を入れることができるのは知りませんでした。
teamikl

2020/03/23 15:34

引数についてはドキュメントでは **options (任意のキーワード引数) となっていて、掘り下げて説明されていませんよね。 参考迄に、 ./Lib/tkinter/messagebox.py からソースコードを辿り ./Lib/tkinter/commondialog.py の Dialog.__init__ で、 `parent`が指定できるのを確認できました。 後、オフトピにですが、if 文の所の`elif Exception:` は、 常にTrueになるので、例外クラスの利用方法としては誤っていて、 このコードの場合は `else:`で済みます。
mintiamegahard

2020/03/24 00:42

ご回答ありがとうございます。助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問