メインコンテンツへスキップ
見出し画像

Pythonライブラリ(GUIツール):tkinter

    1.概要

     GUIツール開発ライブラリのtkinterの使用方法を紹介します。

    2.GUIツールの特徴

     GUIはマウスやキーボードでポチポチできるものになります。「GUI操作ができる=人の判断で選択できる」ため、IF文分岐やAI判断が難しい場合に使用しています。

    【使用例】
    ●管理用としてサーバーに保管するファイルのパスを選択
    ●AIで判断させるのが難しい設計条件

    3.Tkinterウィンドウの操作

    3-1.ウィンドウの作成:tk.Tk()

     GUIで使用する土台ウィンドウを作成します。tk.Tk()でウィンドウを作成して、base.mainloop()で画面表示の維持をします。
     次章以降でbase.mainloop()は一番下に配置していることご留意ください。

    [In]
    import tkinter as tk
    
    base = tk.Tk() #土台(ウィンドウ)を作成
    base.mainloop() #ウィンドウを表示
    画像

    3-2.タイトルの設定:base.title()

     ウィンドウにタイトルをつける場合はbase.title('title名')となります。 

    [In]
    import tkinter as tk
    
    base = tk.Tk() #ウィンドウ作成
    base.title('note紹介用') # タイトルを設定
    base.mainloop()
    画像

    3-3.ウィンドウを隠す/閉じる

     ウィンドウを隠す:base.withdraw(), ウィンドウを閉じる:base.destroy() or base.quit()で実行します。

    [In]
    import tkinter as tk
    import time
    
    base = tk.Tk() #ウィンドウ作成
    base.title('note紹介用') # タイトルを設定
    
    base.withdraw() #ウィンドウを隠す
    base.destroy() #ウィンドウを破棄
    base.mainloop()
    
    [Out]
    base.mainloop()を実行していますがbase.destroy()より処理が完了されています。
    画像

    4.ウィジェット操作1:ウィジェット変数

    4-1.ウィジェット変数のインスタンス化

     ウィジェットが動作したときに取得する戻り値を管理するためのtkinter用変数としてウィジェット変数があります。ウィジェット変数を使用することでウィジェットと戻り値が連動するようになります。

    [ウィジェット変数一覧]※下記は参考用でありコードは動作しません。
    
    str_var = tk.StringVar() #ウィジェット変数:文字列
    int_var = tk.IntVar() #ウィジェット変数:整数
    double_var = tk.DoubleVar() #ウィジェット変数:小数点
    boolean_var = tk.BooleanVar() #ウィジェット変数:真偽値

    4-2.ウィジェット変数の戻り値取得

     ウィジェット変数の戻り値を取得するにはvar.get()で取得します。

    5.ウィジェット操作2:部品の配列指定

     3章で作成した土台にウィジェットを追加していきます。tk.widget(base)でウィジェットを作成でき、メソッドで配置方法を決めます。
     4章では先にウィジェットの配列に関して説明するため次章の内容を一部先取りします。

    5-1.配列1(シンプル):widget.pack()

     ウィンドウの上から並べる場合はpack()を使用します。

    [In]
    import tkinter as tk
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    #ウィジェットの追加
    tk.Button(base, text='ボタン1').pack() #ボタン1を作成
    tk.Button(base, text='ボタン2').pack() #ボタン2を作成
    
    base.mainloop() #ウィンドウを表示
    画像

    【配置の指定1:packi(side=位置)】
     Pack()メソッドはウィジェットを上から順に並べますが、引数(tk.TOPデフォルト, tk.LEFT, tk.RIGHT, tk.BOTTOM)を与えることで位置を変更できます。

    [In]
    import tkinter as tk
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    #ウィジェットの追加
    tk.Button(base, text='ボタン1', width=20).pack() #ボタン作成
    tk.Button(base, text='ボタン2').pack(side=tk.LEFT) #ボタン作成
    tk.Button(base, text='ボタン3').pack(side=tk.RIGHT) #ボタン作成
    
    base.mainloop() #ウィンドウを表示
    画像

    【配置の指定2:packi(anchor=寄せる方向)】
     引数にanchorを指定するとウィジェットを指定方向に寄せることができます。引数はTk.CENTER(中央:デフォルト)Tk.W (左よせ)、Tk.E (右よせ)、Tk.N (上よせ)、Tk.S (下よせ)、 Tk.NW (左上)、Tk.SW (左下)、Tk.NE (右上)、Tk.SE (右下)があります。

    5-2.配列2(行列):widget.grid()

     ウィジェットを格子状行列に配列する場合はpack()ではなくgrid()を使用します。

    [In]
    import tkinter as tk
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    #ウィジェットの追加
    tk.Button(base, text='ボタン1').grid(row=0, column=0) #ボタン作成
    tk.Button(base, text='ボタン2').grid(row=0, column=1) #ボタン作成
    tk.Button(base, text='ボタン3').grid(row=1, column=1) #ボタン作成
    
    base.mainloop() #ウィンドウを表示
    画像

    5-3.配列3(xy座標):widget.place()

     xy座標を指定して配置したい場合はplaceメソッドを使用します。

    [In]
    import tkinter as tk
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    #ウィジェットの追加
    tk.Button(base, text='ボタン1').place(x=0, y=0) #ボタン作成
    tk.Button(base, text='ボタン2').place(x=40, y=60) #ボタン作成
    tk.Button(base, text='ボタン3').place(x=70, y=100) #ボタン作成
    
    base.mainloop() #ウィンドウを表示
    画像

    6.ウィジェット操作3:ウィジェットの追加

     作成したウィンドウに配列を指定してウィジェットを追加していきます。各ウィジェットにアクションを起こした時の動作は下記のとおりです。

    6-1.PUSHボタン:tk.Button()

     pushボタンの追加はtk.Button()であり、width引数で幅も調整できます。

    [In]
    import tkinter as tk
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    #ウィジェットの追加
    tk.Button(base, text='ボタン1').pack() #ボタン1を作成
    tk.Button(base, text='ボタン2').pack() #ボタン2を作成
    
    base.mainloop() #ウィンドウを表示
    画像

    【Pushボタンの動作追加:command引数】
     上記ではボタンを押しても何も動作しません。ボタンを押したときに動作させるためにはtk.Button(command=関数)を入れることで処理できます。

    [In]
    import tkinter as tk
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    #ウィジェットの追加
    def helloworld():
        print('Hello world')
    
    tk.Button(base, text='関数1', command=helloworld).pack() #ボタン1を作成
    tk.Button(base, text='関数2', command=lambda :print('ラムダ関数です')).pack() #ボタン2を作成
    
    base.mainloop() #ウィンドウを表示
    画像

    6-2.ラジオボタン:tk.Radiobutton

     ラジオボタンは選択肢の中から一つだけ選択でき下記の様に記載します。

    [記載例]
    tk.Radiobutton(base, text='表示する文字列', variable=ウィジェット変数, value=戻り値)

     下記では戻り値を整数として、選択したボタンに対して設定した整数値を返すようにしています。

    [In]
    import tkinter as tk
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    radio_var = tk.IntVar() #変数を作成
    radio_var.set(100) #戻り値の初期値設定
    
    articles = {0: "Python", 1: "Ruby", 2: "Perl"} #辞書を作成
    # articles = ["Python", "Ruby", "Perl"] #下記ならリストでも動作可能
    
    tk.Radiobutton(base, text=articles[0], variable=radio_var, value=0).pack() #ラジオボタンを作成
    tk.Radiobutton(base, text=articles[1], variable=radio_var, value=1).pack() #ラジオボタンを作成
    tk.Radiobutton(base, text=articles[2], variable=radio_var, value=2).pack() #ラジオボタンを作成
    
    def getradio():
        print(radio_var.get())
    
    tk.Button(base, text='戻り値出力', command=getradio).pack() #ボタンを作成
    
    base.mainloop() #ウィンドウを表示
    
    画像

    6-3.チェックボックス:tk.Checkbutton()

     チェックボックスでは複数の選択肢を選択できます。ラジオボタンと異なりCheckbutton()はそれぞれのインスタンスにウィジェット変数を渡します。
     また全体としてはウィジェット変数を格納した型(下記では辞書型)となり戻り値はBool(True/False)となります。

    [In_記載例]※実行できません。
    tk.Checkbutton(base, text='表示する文字列', variable=ウィジェット変数)
    
    [Out]
    {0: <tkinter.BooleanVar object at 0x0000022CB2DA19D0>, 1: <tkinter.BooleanVar object at 0x0000022CB2DA17F0>, 2: <tkinter.BooleanVar object at 0x0000022CB2D77E80>}

     サンプルコードでは下記のような構成で作成しました。

    【チェックボックス作成時の構成】
    1.選択肢と同じ数のウィジェット変数を辞書型で作成
    2.FOR文で各選択肢にチェックボックスを作成しウィジェット変数を渡す
    3.FOR文で1.で作成したウィジェット変数の戻り値を取得してTrueだったら文字を返す。

    [In]
    import tkinter as tk
    
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    articles = {0: "Python", 1: "Ruby", 2: "Perl"} #辞書を作成
    checkvals = {i: tk.BooleanVar() for i in range(len(articles))} #選択肢ごとのウィジェット変数
    
    for i in range(len(articles)):
        tk.Checkbutton(base, variable=checkvals[i], text=articles[i]).pack(anchor=tk.W)
    
    def getbox():
        for i in checkvals:
            if checkvals[i].get() == True:
                print(articles[i]) 
    
    tk.Button(base, text='戻り値出力', command=getbox).pack() #ボタンを作成
    
    base.mainloop() #ウィンドウを表示
    画像

    6-4.セレクトボックス:ttk.Combobox()

     一覧から選択するセレクトボックスを使用する場合は、tkinter.ttkモジュールのComboboxメソッドを使用しており戻り値はテキストとなります。

    [In]
    import tkinter as tk
    import tkinter.ttk as ttk
    
    base = tk.Tk() #土台(ウィンドウ)を作成
    
    var_str = tk.StringVar() #変数を作成
    
    languages = ["Python", "Ruby", "Perl"] #配列作成
    ttk.Combobox(base, textvariable=var_str, values=languages).pack()
    
    def getselbox():
        print(var_str.get())
    
    tk.Button(base, text='戻り値出力', command=getselbox).pack() #ボタンを作成
    base.mainloop() #ウィンドウを表示
    画像

    6-5.ラベル:tk.Label()

     ラベルはtk.Label()で作成します。下記の通り文字表示だけのためインタラクティブな動作はなく戻り値もありません。

    [In]
    import tkinter as tk
    
    base = tk.Tk()
    
    tk.Label(base, text="デフォルト").pack()
    tk.Label(base, text="赤", bg='red', width=20).pack()
    tk.Label(base, text="緑", bg='green').pack(side=tk.LEFT)
    tk.Button(base, text="ボタン").pack(side=tk.RIGHT)
    
    base.mainloop()
    画像

    6-6.テキストボックス:tk.Entry()/tk.Label()

     テキストボックスに値を入力するにはtk.Entry()、表示する場合はtk.Label()を使用します。参考までにウィジェット変数から値も取得します。

    [In]
    import tkinter as tk
    
    base = tk.Tk()
    val_str = tk.StringVar() #ウィジェット変数:文字列
    
    tk.Entry(base, textvariable=val_str).pack() #入力値->val_str
    tk.Label(base, textvariable=val_str).pack() #val_str->表示
    
    tk.Button(base, text="OK", command=lambda: print(val_str.get())).pack()
    
    base.mainloop()
    画像

    7.メッセージボックス

     Tkinterはメッセージボックスを表示することができ、戻り値に応じて処理を変更することができます。

    【メッセージボックスの種類】
    ●askokcancel:OK/キャンセル
    ●askquestion:はい/いいえ
    ●askretrycancel:再試行/キャンセル
    ●askyesno:はい/いいえ
    ●askyesnocancel:はい/いいえ/キャンセル
    ●showerror:エラーアイコン+メッセージ表示
    ●showinfo:インフォアイコン+メッセージ表示
    ●showwarning:警告アイコン+メッセージ表示

     下記では参考として"askyesno"を使用しました。

    [In]
    import tkinter as tk
    import tkinter.messagebox as msg
    
    base = tk.Tk() #ウィンドウ作成
    base.withdraw() #ウィンドウを隠す
    
    res = msg.askyesno('Windowのタイトル', '本文')
    
    print(res) #戻り値表示※面倒なのでbase.mainloop()はここでは削除
    画像

    8.メニュー表示

    8-1.メニューバーおよびアイテム表示:tk.Menu()

     ウィンドウにメニューバーを設置して

    [In]
    import tkinter as tk
    
    base = tk.Tk()
    menubar = tk.Menu(base) #メニュー作成
    base.config(menu=menubar) #メニューを設定
    
    tab1 = tk.Menu(menubar) #メニューのタブ作成
    menubar.add_cascade(label="タブ1", menu=tab1) #メニューのタブにタブ1を追加
    tab1.add_command(label='タブ1-1', command=lambda: print('タブ1-1')) #タブ1にタブ1-1を追加
    tab1.add_command(label='タブ1-2', command=lambda: print('タブ1-2')) #タブ1にタブ1-2を追加
    
    base.mainloop()
    画像

    8-2.アイテムに機能追加

     メニューバーのアイテムとして①開いたファイルのパスを取得、②ウィンドウを閉じる処理を加えてみます。

    [In]
    import tkinter as tk
    import tkinter.filedialog as dialog
    
    base = tk.Tk()
    menubar = tk.Menu(base) #メニュー作成
    base.config(menu=menubar) #メニューを設定
    
    tab1 = tk.Menu(menubar)
    menubar.add_cascade(label="ファイル", menu=tab1)
    tab1.add_command(label="ファイル選択", command=lambda: print(dialog.askopenfilename()))
    tab1.add_separator() #アイテムを区切り線にする
    tab1.add_command(label="終了", command=lambda :base.destroy())
    
    base.mainloop()
    画像

    あとがき

     学んだ資料が分かりにくくて落とし込みしてたら10hかかった・・・・まだ下が残ってるけど使うタイミングで調整していく。

    【追加予定】
    ●画像を表示。from PIL import ImageTkのImageTk.PhotoImage使用
    ●ファイルを保存:dialog.asksaveasfilename()
    ●ウィンドウにフレーム追加:tk.Frame(base, relief, boarderwidth)

     
     

    KIYO

     
     
    普段は製造業で企画/開発/設計しております。記事はプログラミング・機械学習、IoT関係の記事をメインで作成し、なるべく1つの記事で知りたいことを網羅していきます。内容は学術的より実装・アウトプット(ほしくなるもの)を重視して作成しています。 面白そうな仕事があればやりたいです!

    あなたへのおすすめ