wxPythonでzipファイルの情報を表示するプログラムを書いた

wxPython In Action』を読んでいる途中。今7章。
とりあえずプログラムを組んでみた。標準モジュールのzipfileを使ってzipファイル中の圧縮されたファイルに関連する情報を表示する。

使い方

  1. メニューバーから[ファイル]->[開く]でファイル選択ダイアログからzipファイルを選択する。
  2. ウィンドウにzipファイル中の情報が表示される。

プログラムを組んで感じたのは、wxPythonのドキュメントがわりと貧弱なのでwxWidgetsのドキュメントを漁ってwxPythonのドキュメントと照らし合わせながらこんな感じかな〜と進めていかざるを得ないのがなんとも、、という。もちろん良いところもあって、C++でやるより柔軟にかけるし型名のタイプだけで腱鞘炎になるんじゃないだろうかとか心配しなくて済むし、珍妙なマクロでイベントを設定せずにすむので悪いというわけじゃないんだけれども、日本語資料も乏しかったり。wxPythonやろうという人は買えるなら『wxPython In Action』は買っといたほうが学習時間を大幅に節約できると思う。すぐにあたれる紙の資料があるのは便利なので。

# coding: utf-8

from zipfile import ZipFile
import wx

class Model(object):
    def __init__(self):
        self.listener = []
    def update(self):
        for listener in self.listener:
            listener()
    def addListener(self, listener):
        self.listener.append(listener)

class ZipReader(Model):
    """__call__でzipファイルの情報を読み込む
    """
    def __init__(self, mapper):
        # mapperはラベルとクロージャのペア
        Model.__init__(self)
        self.labels = map(lambda x: x[0], mapper)
        self.manips = map(lambda x: x[1], mapper)
        self.filenames = []
    def __call__(self, filepath):
        filelist = ZipFile(open(filepath)).filelist
        self.infos = [[f(entry) for f in self.manips] for entry in filelist]
        self.update()
    def __iter__(self):
        return iter(self.infos)

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "zip read", size=(600,400))

        # menu
        mfile = wx.Menu()
        mfile.Append(1, "開く")
        menubar = wx.MenuBar()
        menubar.Append(mfile, "ファイル")
        self.SetMenuBar(menubar)
        self.Bind(wx.EVT_MENU, self.OnFileSelect)
        
        # ZipReader
        self.reader = ZipReader([
            ("ファイル名",   lambda x: x.filename),
            ("サイズ",       lambda x: x.file_size),
            ("最終更新時刻", lambda x: "%d/%02d/%02d" % x.date_time[:3]),
            ("圧縮率",       lambda x: "%.2f" % (float(x.compress_size) / x.file_size)),
            ("コメント",     lambda x: x.comment)])
        self.reader.addListener(self.OnOpenZip)
 
        # listctrl
        self.filelist = wx.ListCtrl(self, -1, style=wx.LC_REPORT)
        for i,label in enumerate(self.reader.labels):
            self.filelist.InsertColumn(i, label)
       
    def OnFileSelect(self, e):
        # ファイル選択ダイアログでzipファイルを読み込んで更新
        dialog = wx.FileDialog(self, "zipファイルを選択してください", wildcard="*.zip")
        dialog.ShowModal()
        self.reader(dialog.GetPath())
        dialog.Destroy()

    def OnOpenZip(self):
        # ウィンドウに情報を表示させる
        self.filelist.DeleteAllItems()
        for info in self.reader:
            self.filelist.Append(map(str, info))
         

if __name__ == '__main__':
    app = wx.PySimpleApp()
    Frame().Show()
    app.MainLoop()

何やらwx.lib以下に楽しげなものがたくさんあるみたいなのであとでチェックする。

wxPython in Action

wxPython in Action

追記:wx.lib.mixins.listctrl.ListRowHighlighterを継承して行毎にハイライトする機能を実装できた。