Python
初心者
bind
Python3
wxpython

【Python】wxPythonを使ってフォルダ選択ダイアログを作成してみた

  

  

  

この記事はPythonど素人が趣味で適当に書いたものです。

そのつもりでお読みください。あと助けて下さい。


wxPythonとは?

GUIアプリケーション作成ツールです。

使い方とかもろもろ【こちら】で網羅できました。ありがとうございます。


フォルダ選択ダイアログ

よく見かける[参照]を押したらフォルダを選択できるダイアログが出てくるアレです。

最終的に選択した2種類のフォルダの中身を比較し、

中身の異なるフォルダを片方に移動&削除までやりたいです。

(まだできてないのでこの記事はフォルダ選択ダイアログを表示して終わります)


Windowを作成

Frame(枠)-Panel(UIを置くパネル)-Button(押したら何かしら起きるボタン)

の順番に作ります。


Frame(枠)

これで枠ができました。

import wx

class Main(wx.Frame):

def __init__(self, parent, id, title):

wx.Frame.__init__(self, parent, id, title, size=(500, 300))

__init__はPythonのコンストラクタらしいです。

class Main(wx.Frame)←ここではFrameクラスを継承してるっぽいです。

現時点でわかったのはここまでです。

wx.Frame.__init__

↑間違えているかもしれませんがFrameクラスのコンストラクタであると解釈しました。

以下、wxPythonの公式ドキュメントに記載されていた__init__です。


__init__ (self, parent, id=ID_ANY, pos=DefaultPosition, size=DefaultSize, style=TAB_TRAVERSAL, name=PanelNameStr)



Panel(UIを置くパネル)

これでパネルができました。

panel = wx.Panel(self, id=wx.ID_ANY)

以下、wxPythonの公式ドキュメントに記載されていたwx.Panelです。


Panel(parent, id=ID_ANY, pos=DefaultPosition, size=DefaultSize,

style=TAB_TRAVERSAL, name=PanelNameStr)


これを見た感じだと、

第一引数に当たるselfには先程作ったFrameが、

第二引数にはidは何でもいいですよという意味に当たるwx.ID_ANYが入っている

みたいなところでしょうか。

つまり、Panelの親はFrameですよってことなんでしょうきっと、うん。


Button(押したら何かしら起きるボタン)

二つのボタンができました。(ついでにボタンの説明も追加してます)

        # 旧プロジェクトファイル選択ボタン

wx.StaticText(panel, wx.ID_ANY, label="旧プロジェクト", pos=(10, 10))
choose_button_old = wx.Button(panel, label="フォルダの選択", pos=(350, 25))

# 最新プロジェクトファイル選択ボタン
wx.StaticText(panel, wx.ID_ANY, label="最新プロジェクト", pos=(10, 60))
choose_button_latest = wx.Button(panel, label="フォルダの選択", pos=(350, 75))

wx.StaticText←文字通り、すたてぃっくなテキストです。親はPanelです。

pos=(横,縦)でいい感じの位置に配置してます。

wx.Buttonがボタンです。こちらの親もPanelです。

後で使うので変数に代入しています。


イベントハンドラ呼び出し

Bindメソッドは【ここ】に助けてもらいました。

 self.old = wx.TextCtrl(panel, wx.ID_ANY, pos=(10, 30), size=(320, 20))

choose_button_old.Bind(wx.EVT_BUTTON, self.choose_folder_old)

self.latest = wx.TextCtrl(panel, wx.ID_ANY, pos=(10, 80), size=(320, 20))
choose_button_latest.Bind(wx.EVT_BUTTON, self.choose_folder_latest)

def choose_folder_old(self, event):
""" フォルダの選択ボタンを押すと呼ばれるイベント。フォルダ選択ダイアログを開き、choose_textに反映 """

folder = wx.DirDialog(self, style=wx.DD_CHANGE_DIR,
message="保存先フォルダ")

if folder.ShowModal() == wx.ID_OK:
folder_path = folder.GetPath()
folder.Destroy()
self.old.SetLabel(folder_path)

def choose_folder_latest(self, event):
""" フォルダの選択ボタンを押すと呼ばれるイベント。フォルダ選択ダイアログを開き、choose_textに反映 """

folder = wx.DirDialog(self, style=wx.DD_CHANGE_DIR,
message="保存先フォルダ")

if folder.ShowModal() == wx.ID_OK:
folder_path = folder.GetPath()
folder.Destroy()
self.latest.SetLabel(folder_path)

ボタンを押したらダイアログが出てきて任意のフォルダを押すと

テキストボックスの中にパスが表示されます。

wx.TextCtrlがテキストボックスを作るクラスで

テキストボックスにはこちらから入力もできます。

Bindメソッドでボタンを押すというイベント(wx.EVT_BUTTON)に

choose_folder_oldchoose_folder_latestという自分で定義したメソッドを

イベントハンドラとして呼び出しています。

似たような処理(ほぼ完全一致)のメソッドを二つ定義しているので、

渡した引数に応じて処理を変えれるようにしたかったのですが、

上手くいきませんでした。

やり方わかる方教えて下さい。


最終的なコード


import wx

class Main(wx.Frame):

def __init__(self, parent, id, title):

wx.Frame.__init__(self, parent, id, title, size=(500, 300))
panel = wx.Panel(self, id=wx.ID_ANY)

# 旧プロジェクトファイル選択ボタン
wx.StaticText(panel, wx.ID_ANY, label="旧プロジェクト", pos=(10, 10))
self.old = wx.TextCtrl(panel, wx.ID_ANY, pos=(10, 30), size=(320, 20))
choose_button_old = wx.Button(panel, label="フォルダの選択", pos=(350, 25))
choose_button_old.Bind(wx.EVT_BUTTON, self.choose_folder_old)

# 最新プロジェクトファイル選択ボタン
wx.StaticText(panel, wx.ID_ANY, label="最新プロジェクト", pos=(10, 60))
self.latest = wx.TextCtrl(panel, wx.ID_ANY, pos=(10, 80), size=(320, 20))
choose_button_latest = wx.Button(panel, label="フォルダの選択", pos=(350, 75))
choose_button_latest.Bind(wx.EVT_BUTTON, self.choose_folder_latest)

# 画面を表示
self.Show(True)
# 画面の表示位置を中央に
self.Centre()

def choose_folder_old(self, event):
""" フォルダの選択ボタンを押すと呼ばれるイベント。フォルダ選択ダイアログを開き、choose_textに反映 """

folder = wx.DirDialog(self, style=wx.DD_CHANGE_DIR,
message="保存先フォルダ")

if folder.ShowModal() == wx.ID_OK:
folder_path = folder.GetPath()
folder.Destroy()
self.old.SetLabel(folder_path)

def choose_folder_latest(self, event):
""" フォルダの選択ボタンを押すと呼ばれるイベント。フォルダ選択ダイアログを開き、choose_textに反映 """

folder = wx.DirDialog(self, style=wx.DD_CHANGE_DIR,
message="保存先フォルダ")

if folder.ShowModal() == wx.ID_OK:
folder_path = folder.GetPath()
folder.Destroy()
self.latest.SetLabel(folder_path)

def main():
app = wx.App(False)
Main(None, wx.ID_ANY, "Project Updater")
app.MainLoop()

if __name__ == "__main__":
main()

こんな感じです。

projectUpdate.png

パス比較して、一致しないサブディレクトリだけのリスト作って

うんぬんかんぬんすればいけるんじゃないかと思ってます。

もしそれでいけたら忘れないうちにまた書きます。

まだまだ粗削りですが続き書きました→こちら