即効!Python: tkinterのGUIプログラミング – Widgetの初歩

python

Pythonのライブラリや構文などの基礎をPythonで作る実践プログラムのソースコードを踏まえてを解説します。

前回はファイル操作の基本としてフォルダ名を一括変換するプログラムを作成しました。

即効! pythonプログラミング「フォルダ名変換」
Python実践プログラムのソースコードを使ってPythonのライブラリや構文などの基礎を解説します。今回はosモジュールを使った「ファイル操作」の基本の学習です。指定した文字列が含まれるフォルダを探してフォルダ名中の文字列を変換します。

しかしこれは変換前後の文字列をコードに書き込まなければなりませんので誰もが使うには少々ハードルが高いものになっています。

そこで今回は誰もが使えるような操作パネル(widget)の作り方を解説します。

プログラムの全容

機能

プログラムを走らせると下のような操作パネルが出ます。

この「変換対象文字列」に変更したい元の文字列を、「変換後の文字列」に変更した後の文字列を入れ「変換」ボタンを押すとカレントフォルダにある「変換対象文字列」を含むフォルダを全て抽出してその文字列だけ変換します。

ソースコード

import os
MyPath='./'

import tkinter as tk#1. tkinterモジュールをtkという名前でインポート
root=tk.Tk()#2.Windowを作る.
root.geometry('400x100+200+100')#3.Windowのサイズと位置を決める
root.title('フォルダ名の部分置き換え')#4.Womdowにタイトルをつける

def ReplaceName():
    Contents=os.listdir(MyPath) 
    clist=[] 
    
    for f in Contents:
        if os.path.isdir(f)==True: 
            clist.append(f)
        X_before=entry1.get()
        X_after=entry2.get()
        
        for dirName in clist:
            try: 
                if X_before in dirName:
                    NewName=dirName.replace(X_before,X_after)
                    os.rename(dirName,NewName)
            except: 
                print(dirName,'は例外')
        
# Window上にFrameを作成する
frame1=tk.Frame(root) 
frame2=tk.Frame(root)
frame3=tk.Frame(root)

# Widgetを作成・配置する
label1=tk.Label(frame1,text='変換対象文字列: ',padx=5)
entry1=tk.Entry(frame1,width=40)
label2=tk.Label(frame2,text='変換後の文字列: ',padx=5)
entry2=tk.Entry(frame2,width=40)
button=tk.Button(frame3,text='変換',command=ReplaceName)

frame1.pack()
frame2.pack()
frame3.pack()

label1.pack(side='left')
entry1.pack()

label2.pack(side='left')
entry2.pack()

button.pack()

root.mainloop()

上記のソースコードを使ってWidgetの作り方を解説します。このままコピペでも使えますので試してみて下さい。

TkinterのGUIプログラミングの初歩

今回使用するTkinterモジュールはTkというGUI開発のためのウィジェット・ツールキットをpythonに取り込むインターフェースです。これを使ってWindow>Frame>Widgetを作成・配置してGUIの操作パネルを作ります。

Window>Frame>Widgetの関係

Window,Frame,WidgetはTkinterの構成要素です。

・Window: Tkinterで作るGUIコントロールパネルの全体

・Frame: Window上に配置され、その中に各Widgetを配置できる枠

・Widget: 表示・操作などの機能を持ったGUIの部品

それぞれの関係を図で簡単に表すと以下のようになります。

プログラミングの流れ

Windowを作る

最初にそれぞれのWidgetを配置するための親Windowを作ります。

ソースコード

import os
MyPath='./'

import tkinter as tk#1. tkinterモジュールをtkという名前でインポート
root=tk.Tk()#2.Windowを作る.
root.geometry('400x100+200+100')#3.Windowのサイズと位置を決める
root.title('フォルダ名の部分置き換え')#4.Womdowにタイトルをつける
root.mainloop()#5.Windowを表示し続ける

解説

#1. tkinterモジュールのインポート

tkinterモジュールを”tk”という名前でインポートします。

#2.Tk()関数でWindow作成

Tk()はWindowを作成する関数です。ここではWindowに”root”という名前をつけました。

#3.geometry()関数でWindowのサイズと位置を決定

geometryでWindowのサイズと位置を決めます。

root.geometry(‘X x Y + x +y’) (単位はピクセル)

で横X, 縦YのサイズのWindowを画面の左からx, 上からyの位置に表示します。上記のソースコード中の

root.geometry(‘400×100+200+100’)

では横400,縦100のWindowを画面左端から200,上端から100の位置に表示します。

#4. title()関数でWindowのタイトルを追加

title(XXX)

でWindowに「XXX」というタイトルをつけることができます。

コード中の

root.title(‘フォルダ名の部分置き換え’)

ではWindowのタイトルとして「フォルダ名の部分置き換え」が追加されます。

#5.mainloop()関数でWindowを表示

mainloopはWindowを表示し続けるための無限ループでWindowを閉じるまでループし続け、Windowの生成と破棄を高速に繰り返します。このmainloopがないとWindowが一瞬で消えてしまいます。

Window上にFrameとWidgetを作る

下図のような操作パネル(widget)を作ります。

Windowの中にFrameを3段(frame1,frame2,frame3)作成・配置し、

それぞれのFrameにWidgetを配置します。

ソースコード

# ------- 以下追加 ------

#6.Window上にFrameを作成する
frame1=tk.Frame(root) 
frame2=tk.Frame(root)
frame3=tk.Frame(root)

#7.  Widgetを作成・配置する
label1=tk.Label(frame1,text='変換対象文字列: ',padx=5)#8. Labelを作成
entry1=tk.Entry(frame1,width=40)#9. Entryを作成
label2=tk.Label(frame2,text='変換後の文字列: ',padx=5)
entry2=tk.Entry(frame2,width=40)
button=tk.Button(frame3,text='変換')#10. Buttonを作成
frame1.pack()#11. フレームをwindow内で配置
frame2.pack()
frame3.pack()

label1.pack(side='left')#12. widgetをフレーム内で配置
entry1.pack()

label2.pack(side='left')
entry2.pack()

button.pack()

root.mainloop()#<-この行は最後尾に移動

(root.mainloop行は最後尾に移動します)

解説

#6. Frameの作成

Window上に配置するFrameを作ります。

frame1=tk.Frame(root)

で”root”という親Window上に置く”frame1”というFrameを作りました。同様に”frame2”,”frame3”も作ります。ただしこの段階ではFrameはまだ配置されていません。

今回は使っていませんが”root”の後にオプションを追加してFrameの見た目を変更することができます。これについてはいろいろなサイトで紹介していますので参考にして下さい。

#7.Widgetの作成

TkinterではさまざまなWidgetが用意されていますがその中から今回は

  • Label: 文字を表示
  • Entry: 入力用のテキストボックス
  • Button: クリックするとイベント処理を実行するボタン

の三つを使います。

#8.Label widgetの作成

Label widgetは

tk.Label(親Frame,オプション,・・・)

と記述して作成します。

label1=tk.Label(frame1,text=’変換対象文字列: ‘,padx=5)

では”frame1”という親Frameにtext=’変換対象文字列: ‘ というオプションで「変換対象文字列: 」という文字列を表示し、padx=5 というオプションでLabel Widet内の左右スペースを5ピクセル空けます。(デフォルトは1)

これを”label1”とします。

参考)

tk.Labelのオプション(海外サイト) https://tkdocs.com/shipman/label.html

#9.Entry widgetの作成

Entry  widgetは

tk.Entry(親Frame,オプション,・・・)

と記述して作成します。

entry1=tk.Entry(frame1,width=40)

では”frame1”という親Frameにwidth=40というオプションで 半角40文字分の文字が入る幅のテキストボックスを表示します。(幅はピクセルではなく半角文字数で表すことに注意しましょう。)

参考) tk.Entryのオプション(海外サイト)  https://tkdocs.com/shipman/entry.html

同様に”frame2”に配置する”label2”,” entry2”というWidgetを作成します。

#10. Button widgetの作成

Button widgetは

Button widget=tk.Button(親Frame,オプション,・・・)

と記述して作成します。

button=tk.Button(frame3,text=’変換’)

では”frame3”という親Frameにtext=’変換’ で「変換」という文字列を表示したボタンを配置します。

ボタンはクリックして何らかのイベントを呼び出すwidgetです。イベントを呼び出すCommandオプションは後述します。

参考) tk.Buttonのオプション(海外サイト)  https://tkdocs.com/shipman/button.html

#11. Frameをwindow内に配置

WidgetをFrame内に配置する場合、およびFrameをWindow内に配置する場合にジオメトリマネージャを使います。

ジオメトリマネージャには以下の三つがあります。

  • pack() : 指定した方向にwidgetを並べて配置する
  • grid() : windowまたはframeを格子状に分けて行と列でwidgetを配置する
  • place() : widgetを座標で配置する

ここではpack()を使います。

オプションを指定しなければ上から順番に並べますので

frame1.pack()

frame2.pack()

frame3.pack()

では”frame1”,”frame2”,”frame3”が以下のように上から下へ並びます。

それぞれのFrameにWidgetを配置します。

#12. widgetをframe内に配置

label1.pack(side=’left’)

entry1.pack()

の”label1”,” entry1”はともに親Frameが”frame1”ですので同じFrame内での配置を決めます。

配置の方向はデフォルトでは上から下に向かって並べますが、labe1とentry1を横に並べたいのでside=’left’というオプションを指定して左から横に並べます。

“label2”と”entry2”も同様に”frame2”内で左から横に並べます。

label2.pack(side=’left’)

entry2.pack()

最後に

button.pack()

で”button”を”frame3”に配置して各widgetの配置が完了です。

ここまでで操作パネルの外観は完成しました

次に「変換」ボタンに文字列変換プログラムを紐付けます。

ボタンクリック時の処理を追加する

ソースコード

button=tk.Button(frame3,text='変換',command=ReplaceName)#13. commandオプションをbuttonウィジェットに追加

前述のコードの13行目を上記コードと差し替えて、前述のコードの1行目「——- 以下追加 ——」を下記コードと置き換えます。

def ReplaceName():#14. 関数を定義
    print('ボタンがクリックされた')# お試し処理

解説

#13.commandオプションをbuttonウィジェットに追加

commandオプションによりボタンがクリックされると関数またはメソッドが呼び出されます。

button=tk.Button(frame3,text=’変換’,command=ReplaceName)

ではcommandオプションによって”ReplaceName”という関数が呼び出されます。

#14.defによるユーザー定義関数の定義

ユーザー定義関数の構文は以下のようになります。

def 関数名(引数, …):

___…任意の処理…

___return 戻り値

上記のコードではお試しとしてReplaceName関数が呼び出されると

print(‘ボタンがクリックされた’)

が実行され「ボタンがクリックされた」と表示するようにしました。

以上でボタンをクリックするとユーザー定義関数が処理されるコードができました。

ボタンクリックでテキストボックスの文字列を読み込み文字列変換を行う

いよいよ「フォルダ名変換」プログラムを完成させます。

前回、変換したい文字列を含むフォルダを抽出してその文字列を変換するプログラムを作成していますので、それをユーザー定義関数としてReplaceName関数に組み込みます。

ソースコード

import os#15. osモジュールをインポート

1行目でosモジュールをインポートします。

def ReplaceName():
    Contents=os.listdir(MyPath) 
    clist=[] 
    
    for f in Contents:
        if os.path.isdir(f)==True: 
            clist.append(f)
        X_before=entry1.get()#16. Entryウィジェットのテキストボックスからgetメソッドで文字列を取得
        X_after=entry2.get()
        
        for dirName in clist:
            try: 
                if X_before in dirName:
                    NewName=dirName.replace(X_before,X_after)
                    os.rename(dirName,NewName)
            except: 
                print(dirName,'は例外')

ReplaceName関数を上記と置き換えます。

解説

#15.osモジュールをインポートする

osモジュールのインポートとパスの定義は一度行えばよいので最初に持ってきます。

#16. Entryウィジェットのテキストボックスからgetメソッドで文字列を取得

getメソッドで“entry1”のテキストボックスに書かれた値を取得します。

X_before=entry1.get()

では”entry1”のテキストボックスに書かれた文字列を”X_before”に代入します。

同様に

X_after=entry2.get()

で”entry2”のテキストボックスの文字列を”X_after”に代入します。

これで「変換対象文字列」と「変換後の文字列」を取得して変換する操作パネルが完成しました。

まとめ

今回は基礎的なウィジェットを使いましたが、それぞれのウィジェットに様々なオプションやメソッドがありますのでこれらを試してみるとウィジェットの飾り方、表示のしかたが把握できると思います。

ところでウィジェットを作って扱いが簡単になったとは言え、まだPython環境が必要だという制約があります。そこで次回は今回作ったプログラムをWindows用のexe/Mac用のappにして、Python環境がなくても実行できるようにします。

コメント

タイトルとURLをコピーしました