Pythonのtkinterでメッセージボックスだけを出したいのに、何もない小さなウインドウ(謎ウインドウ)が一緒に出てきて、処理が止まってしまうことがあります。
結論から言うと、謎ウインドウの正体は tkinterが自動で作るルートウインドウ です。先に自分でルートウインドウを作って隠すか、使い終わったら root.destroy() で閉じれば解決します。
要点
- messageboxは親になるウインドウが必要で、無ければ勝手にルートウインドウが作られます
- よく紹介されているのは
root.withdraw()で隠す方法です - 私の環境では、withdrawするとメッセージボックスまで見えなくなりました
root.destroy()でルートウインドウを閉じる方法なら、確実に先へ進めました
謎ウインドウが出て処理が止まる

次のコードを動かすと、メッセージボックスと一緒に謎ウインドウが出てきます。メッセージボックスのOKを押しても謎ウインドウが残り、最後の「OK」が表示されませんでした。
import tkinter as tk
from tkinter import messagebox
messagebox.showinfo('NEXT', 'つぎへ')
print('OK')
原因はルートウインドウの自動生成
tkinterのウインドウには、必ず一番大もとになる「ルートウインドウ」が必要です。messageboxを呼んだときにルートウインドウが無いと、tkinterが自動で作ります。これが謎ウインドウの正体です。
自動で作られたルートウインドウは誰も閉じないので、プログラムがそこで待ち続けてしまいます。
対処法1:root.withdraw()で隠す
調べると、多くの記事で紹介されているのがこの方法です。先にルートウインドウを自分で作り、withdraw() で隠してからメッセージボックスを出します。
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.withdraw()
messagebox.showinfo('NEXT', 'つぎへ')
print('OK')
多くの人はこれでうまくいっているようです。ところが私の環境では、謎ウインドウと一緒にメッセージボックスまで見えなくなってしまいました。
withdrawでメッセージボックスが出ないとき
はっきりした原因はわかっていませんが、メッセージボックスが消えたのではなく、ほかのウインドウの後ろに隠れている可能性があります。その場合は、ルートウインドウを最前面に設定し、親として指定すると前に出てくるはずです。私の環境ではまだ試していないので、うまくいかないときは次の対処法2を使ってください。
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.withdraw()
root.attributes('-topmost', True)
messagebox.showinfo('NEXT', 'つぎへ', parent=root)
root.destroy()
print('OK')
対処法2:root.destroy()で閉じる
私が最終的に使ったのはこの方法です。ルートウインドウを隠さずに作っておき、メッセージボックスを閉じたら destroy() でルートウインドウごと閉じます。
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
messagebox.showinfo('NEXT', 'つぎへ')
root.destroy()
print('OK')
メッセージボックスが出ている間は空のウインドウも見えますが、OKを押すと両方閉じて、ちゃんと「OK」まで進みました。
見た目は少しかっこ悪いですが、確実に動くので、困ったらまずこの方法を試してみてください。もっとスマートな方法をご存じの方がいたら、コメントで教えてもらえるとうれしいです。
まとめ
- 謎ウインドウの正体は、tkinterが自動で作るルートウインドウです
root = tk.Tk()で先に作り、withdraw()で隠すのが定番の方法です- withdrawでメッセージボックスが見えないときは、最前面の設定か
destroy()で閉じる方法を試してください - 私の環境では
destroy()で閉じる方法が確実でした
tkinterの基本的な使い方は、Python備忘録 Tkinter編② テキスト入力とボタンにまとめています。tkinterで作った計算カードアプリの記事もあります。