LoginSignup
3
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-09-20

きっかけ

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

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0