Pythonのライブラリや構文などの基礎をPythonで作る実践プログラムのソースコードを踏まえてを解説します。
前回はファイル操作の基本としてフォルダ名を一括変換するプログラムを作成しました。
しかしこれは変換前後の文字列をコードに書き込まなければなりませんので誰もが使うには少々ハードルが高いものになっています。
そこで今回は誰もが使えるような操作パネル(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環境がなくても実行できるようにします。
コメント