Help us understand the problem. What is going on with this article?

【Python】tkinterでGUIの表示・非表示?

きっかけ

Windowsのスタートアップに入れて
設定日時になるとウィンドウにメッセージを表示し警告音を出そうとしたのですが
pythonのtkinterでGUIを非表示(destroy)するとpython自体が落ちるので困っていた
勉強不足なのかもしれないけれどメッセージボックスは別のアプリの陰に表示されるし思い通りに操作出来ないし(特にcommandあたり)

ダメなコード?

destroyで非表示(削除が正しい?)にしgui関数で再表示(描画)してやるー!

window_hide.py
import time
import tkinter as tk

import sched

# entry内の文字列をprint
def print_entry():
    global entry
    print(entry.get())

# 3秒経つとprint_entryを呼びます
# 5秒経つとguiを呼びます
def wait():
    s = sched.scheduler(time.time, time.sleep)
    s.enter(3, 1, print_entry)
    s.enter(5, 1, gui)
    s.run()

# ウィンドウをデストロイしwaitを呼びます
def window_hide():
    global root
    root.destroy()
    wait()

# ウィンドウを描画します
def gui():
    global root, entry
    root = tk.Tk()
    root.attributes('-topmost', True)
    root.geometry('+0+0')
    root.title('お知らせ')

    label = tk.Label(root, text='通知です')
    label.pack(fill='x')
    button = tk.Button(root, text='OK', command=window_hide)
    button.pack(fill='x')
    entry = tk.Entry(root)
    entry.pack(fill='x')
    entry.delete(0, tk.END)
    entry.insert(tk.END, 'test')

    root.mainloop()

def main():
    gui()

if __name__ == "__main__":
    main()

初期のコードを消してしまったので適当に書きました間違ってたらごめんなさい

wait関数内で3秒後のprint_entryを呼び出すとエラーで落ちます
ループしないので楽しく無いです

落ちないでprintしループする方法

withdrawで非表示にできるのならば表示する方法があるはず
と検索して出てきたのがdeiconifyです

コード

window_hide.py
import time
import tkinter as tk

import sched

# entry内の文字列をprint
def print_entry():
    global entry
    print(entry.get())

# 3秒経つとprint_entryを呼びます
# 5秒経つとwindow_displayを呼びます
def wait():
    s = sched.scheduler(time.time, time.sleep)
    s.enter(2, 1, print_entry)
    s.enter(5, 1, window_display)
    s.run()

# ウィンドウを表示
def window_display():
    global root
    root.deiconify()

# ウィンドウを非表示にしwaitを呼びます
def window_hide():
    global root
    root.withdraw()
    wait()

# main関数でウィンドウを描画します
def main():
    global root, entry
    root = tk.Tk()
    root.attributes('-topmost', True)
    root.title('お知らせ')

    label = tk.Label(root, text='通知です')
    label.pack(fill='x')
    button = tk.Button(root, text='OK', command=window_hide)
    button.pack(fill='x')
    entry = tk.Entry(root)
    entry.pack(fill='x')
    entry.delete(0, tk.END)
    entry.insert(tk.END, 'test')

    root.mainloop()

if __name__ == "__main__":
    main()

無事にentryの文字列をprintしループしています
※こちらループしますのでご注意ください

最後に

前者のコード

mainloopdestroyしてしまうため非表示中のentryを読み込めずにエラーを起こします
エラーを起こさない様に記述した場合ウィンドウを再描画しているためチョット違った挙動になったりします

後者のコード

あくまでも「非表示」なので非表示中のentryも読み込むことができます
環境によりますが非表示なので再表示で同じ座標に表示されます

追記:
Mac Mojaveの場合は同じ座標でしたが
Xubuntuではウィンドウの状態により真ん中だったり左上だったり
Windowsは手持ちに環境が無いので後に追記します

他に違いのわかる方いらっしゃったらご教示お願いいたします

おまけの戯言

本来は非表示中にラベルやボタンの表示を変えようとしてpythonが落ちてたのですが
再現できるコードが書けないため(おばか)強引にプリントでごまかしてます
多分ですが下記のGitHubに上げたコードはそれを利用してると思います

Qiitaでdeiconifyを検索しても執筆当時は2件
pythonのtkinterだと1件という少なさから記事を書いてみようと思いました
違いもわからないのに!

python attribute root.destroy() と root.quit()の違いは何ですか?の記事もチョット気になります

お知らせ

GitHub始めてみました
拙いコードですが今回の後者のコードを応用して制作しました
GitHub

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away