(2020-05-11 初稿 - 2021-05-12 転記・修正 )
はじめに
pythonでユーザからGUIで入力を得るためには、tkinterのsimpledialogを用いると簡単である。
simpledialogは、入力が必要な場面のみダイアログが出るので、筆者のようにCUIをメインに作っている者にはありがたい。
以下は、参考サイト。
- 【python入門者必見!】Pythonのinput関数を解説 | WEBCAMP NAVI
- Python §69 : pandasデータ処理アプリ(6) 入力ボックスについて | hitochan007のブログ(Pythonの勉強ブログ)
- messageboxとsimpledialogのまとめ - Qiita
しかし、ユーザーから複数の入力を得たい場合は、simpledialog では何回も入力、改行を繰り返すことになってしまう。
そこで、シンプルで複数の入力が可能なダイアログを自作することにした。
もちろん、CUI好きな筆者なので、今回のスクリプトも一時的なGUIの利用で、ユーザからの入力値を得たらすぐにGUIを終了するものにした。
ところが、自作してみると、入力値を得ることが簡単ではなかった。
一つの解としては、入力値を受け取る変数をグローバル変数にするというのがある。
以下、参考サイト。
いろいろと試していると、グローバルな変数を使わなくても入力値を得ることができたので、備忘録としてメモを残す。
作成したスクリプト
前提条件が多く前置きが長くなったが、今回作成したスクリプトは、ディレクトリ名(dirname)とファイル名(fname)の2つ値を入力するダイアログである。
(2020-05-12 追記)
別の複数のtkを利用するスクリプトを作成したところ、ウィンドウが消えない現象がありプログラムを変更した。
【補足】
root.withdraw() で ウィンドウを消した状態に
root.deiconfy() で ウィンドウを表示root.quit() guitした後のコードも実行
root.destroy() destroy後のコードは実行されない
#!/usr/bin/env python3 #coding: UTF-8 import sys import tkinter def ask_df(): root = tkinter.Tk() root.withdraw() # 2020-05-12 追記 root.title("Next Entry") root.geometry("400x120") # function def ok_get(event): root.quit() #ラベル label1 = tkinter.Label(text='Directory:') label2 = tkinter.Label(text='Filename:') label1.place(x = 20, y = 20) label2.place(x = 20, y = 50) #エントリー editbox1 = tkinter.Entry(width=40) editbox1.insert(tkinter.END,"Directory Name") editbox1.place(x=100, y=20) editbox2 = tkinter.Entry(width=40) editbox2.insert(tkinter.END,"File Name") editbox2.place(x=100, y=50) #ボタン button1 = tkinter.Button(text='OK') button1.bind("<Button-1>", ok_get) button1.place(x=300, y=80) # Enter でも OK root.bind('<Return>', ok_get) root.deiconfy() # 2020-05-12 追記 root.mainloop() root.withdraw() # 2020-05-12 追記 return editbox1.get(), editbox2.get() # mainloop終了後 値return if __name__ == "__main__": dir, fname = ask_df() print("Dirname:", dir) print("Filename:", fname)
スクリプトの拡張
他のサイトに入力をクリアする方法の記載があったので、参考までに上記スクリプトに加えてみた。
いろいろなオプションやボタンをつける際の参考に。
#!/usr/bin/env python3 #coding: UTF-8 import sys import tkinter def ask_df(): root = tkinter.Tk() root.withdraw() # 2020-05-12 追記 root.title("Next Entry") root.geometry("400x120") # function def deletevalue(event): #エントリーの中身を削除 editbox1.delete(0, tkinter.END) editbox2.delete(0, tkinter.END) def ok_get(event): root.quit() #ラベル label1 = tkinter.Label(text='Directory:') label2 = tkinter.Label(text='Filename:') label1.place(x = 20, y = 20) label2.place(x = 20, y = 50) #エントリー editbox1 = tkinter.Entry(width=40) editbox1.insert(tkinter.END,"Directory Name") editbox1.place(x=100, y=20) editbox2 = tkinter.Entry(width=40) editbox2.insert(tkinter.END,"File Name") editbox2.place(x=100, y=50) #ボタン button1 = tkinter.Button(text='OK') button1.bind("<Button-1>", ok_get) button1.place(x=300, y=80) button2 = tkinter.Button(text='Clear') button2.bind("<Button-1>", deletevalue) button2.place(x=200, y=80) # Enter でも OK root.bind('<Return>', ok_get) root.deiconfy() # 2020-05-12 追記 root.mainloop() root.withdraw() # 2020-05-12 追記 return editbox1.get(), editbox2.get() if __name__ == "__main__": dir, fname = ask_df() print("Dirname:", dir) print("Filename:", fname)
おわりに
筆者は、pythonもtkinterもど素人だが、使って覚えれば良いかなと考えている。
さらに、良い方法があったら、gmailのhymd3あてまで、教えてください。