AA管理ツール SETZER ver0.02 公開

Download SETZER ver.0.02.zip
※最新版はhoehoeSoft

変更点

  • リストボックスの最大表示数を設定可に
  • ツールチップ表示のウィンドウ最大値を調節可に
  • タスクバーに表示するかどうかを設定可に
  • 何文字入力された時点でMigemo検索を行うかを設定可に
  • 文字を入力してもリストが変更しないときはちらつかせない
  • アイコンを変えた
  • ソースコードを入れた


wxPythonでブックマーク管理ツールを作ろう!

あいさつ

つかさです。
今回は番外編です。ブックマーク管理ツールを作ってみます。AA管理ツールで学んだことを応用します。


準備

今回作るプログラムは、あらかじめブックマークを手動でテキストファイルに書き込んでおき、それを読み込む、という形式をとります。
まずそのブックマークを書き込んだファイルを作りましょう。

  • bookmark.ini
つかさのほえほえ日記 |http://d.hatena.ne.jp/tukasa1919/
はてなブックマーク |http://b.hatena.ne.jp/tukasa1919/
2ちゃんねる サーバ負荷監視所 |http://ch2.ath.cx/
Google リーダー | http://www.google.com/reader/view/#overview-page
PPx help | http://homepage1.nifty.com/toro/ppxhlp.html
Twitter | http://twitter.com/
wxPythonリファレンス | http://wxwindowsjp.sourceforge.jp/docs/html/wx/wx26.htm#classref
gmail | https://mail.google.com/mail
簡易AAエディタ | http://iranegi.s5.xrea.com:8080/2ch/aaedit/aaedit.php

"|"で区切っています。サイト名とurlが対になってます。これをスクリプトと同じフォルダにおくことで、ブックマークを読み込みます。
また、Migemoも使うので、それに関係するファイル(migemo.dll migemo.pyd Dict)も、同じフォルダに用意しておいてください。
では次に、このファイルを読み込むプログラムを作成します。


GUIを作る

まずはGUIを作るところからはじめましょう。

  • Bookmark01.py
import wx

class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id)
        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)

class MyApp(wx.PySimpleApp): 
    def OnInit(self):
        self.TxtFrm = MyTxtFrm(None, -1)
        self.TxtFrm.SetSize( (180, 200) )
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()

wxPythonでAA管理ツールをつくろう!第一回 GUIを作ると全く同じですので、詳しくはそこを参照してください。

リストを作る

次に、bookmark.iniを読み込み、サイト名とurlが対になった辞書を作り、サイト名のリストをセットします。

  • Bookmark02.py
import wx

class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1)

        bf = open("bookmark.ini")
        booklist = bf.readlines()

        booklist = map((lambda x: x.decode("shift-jis").strip()),booklist)
        booklist = map((lambda x: x.rsplit("|")),booklist)
        booklist = map((lambda x: tuple(x)),booklist)

        self.BookDict = {}
        for x in booklist:
            name = x[0].strip()
            url = x[1].strip()
            self.BookDict[name] = url
        
        self.site_list = self.BookDict.keys()
        self.LBox.Set(self.site_list)
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)

class MyApp(wx.PySimpleApp): 
    def OnInit(self):
        self.TxtFrm = MyTxtFrm(None, -1)
        self.TxtFrm.SetSize( (180, 200) )
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()


辞書の作成
        bf = open("bookmark.ini")
        booklist = bf.readlines()

        booklist = map((lambda x: x.decode("shift-jis").strip()),booklist)
        booklist = map((lambda x: x.rsplit("|")),booklist)
        booklist = map((lambda x: tuple(x)),booklist)

        self.BookDict = {}
        for x in booklist:
            name = x[0].strip()
            url = x[1].strip()
            self.BookDict[name] = url

まずは辞書を作るところから。"|"を区切り文字にして、サイト名とurlの対を取り出します。
次いで空の辞書self.BookDictを作り、サイト名をキーに。urlを値にして一つずつ登録します。
これで次のような辞書ができます。

{'つかさのほえほえ日記' : 'http://d.hatena.ne.jp/tukasa1919/',
'はてなブックマーク' : 'http://b.hatena.ne.jp/tukasa1919/',
'2ちゃんねる サーバ負荷監視所' : 'http://ch2.ath.cx/',
'Google リーダー' : 'http://www.google.com/reader/view/#overview-page',
以下略}
リストボックスに登録
        self.site_list = self.BookDict.keys()
        self.LBox.Set(self.site_list)

次に、この辞書からサイト名のリストを作ります。キーのリストをkeys()で作成して、それをListBoxにセットします。

これで見た目は完成です。
次に、カーソル移動とMigemoによるインクリメンタルサーチができるようにします。

カーソル移動とインクリメンタルサーチの追加(コピペ)

  • Bookmark03.py
import wx,migemo,re

migemo_object = None

class IncrementalSearch:
    def __init__(self,pattern,list):
        self.pattern = pattern
        self.new_list = []
        self.old_list = list

    def GetBackList(self):
        global migemo_object
        
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')
        re_pattern = migemo_object.query(self.pattern)
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False
                    
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list


class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1)

        bf = open("bookmark.ini")
        booklist = bf.readlines()

        booklist = map((lambda x: x.decode("shift-jis").strip()),booklist)
        booklist = map((lambda x: x.rsplit("|")),booklist)
        booklist = map((lambda x: tuple(x)),booklist)

        self.BookDict = {}
        for x in booklist:
            name = x[0].strip()
            url = x[1].strip()
            self.BookDict[name] = url
        
        self.site_list = self.BookDict.keys()
        self.LBox.Set(self.site_list)

        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)


    def OnKeyChar(self,event):
        key = event.GetKeyCode()
        if key ==  wx.WXK_ESCAPE:
            wx.Exit()
        elif key == wx.WXK_UP:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() - 1
            if next >=  0:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(count - 1)
        
        elif key == wx.WXK_DOWN:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() + 1
            if next < count:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(0)

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            fr = self.LBox.GetStringSelection()
            webbrowser.open(self.BookDict[fr])
            wx.Exit()
        else: event.Skip()

    def OnText(self,event):
        word = self.TxtCtr.GetValue()
        isearch = IncrementalSearch(word,self.BookDict.keys())
        try:
            new_list = isearch.GetBackList()
        except:
            return False
        if new_list:
            self.LBox.Set(new_list)
            self.LBox.SetSelection(0)
        else: event.Skip()
        event.Skip()

class MyApp(wx.PySimpleApp): 
    def OnInit(self):
        self.TxtFrm = MyTxtFrm(None, -1)
        self.TxtFrm.SetSize( (180, 200) )
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()

変更したのは以下の点です。

  • reとmigemoをインポート
  • migemoをglobal変数として宣言
  • IncrementalSearchクラスをコピペ
  • OnKeyCharとOnTextの二つの関数をコピペ

そして、

        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)

を__ini__に付け足してます。
やってることはAA管理ツールのコードの流用です。wxPythonでAA管理ツールを作ろう!第六回 PyMigemoでインクリメンタルサーチあたりのコードから該当箇所をコピペしてます。

URLをデフォルトのブラウザで開く

いよいよラストです。
実際にブックマークをブラウザで開けるようにしましょう。変更点は、

  • urlをデフォルトのブラウザで開くためにwebbrowserをインポート
  • OnKeyCharのEnterの箇所

です。

  • Bookmark04.py
import wx,migemo,re,webbrowser

migemo_object = None

class IncrementalSearch:
    def __init__(self,pattern,list):
        self.pattern = pattern
        self.new_list = []
        self.old_list = list

    def GetBackList(self):
        global migemo_object
        
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')
        re_pattern = migemo_object.query(self.pattern)
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False
                    
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list


class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1)

        bf = open("bookmark.ini")
        booklist = bf.readlines()

        booklist = map((lambda x: x.decode("shift-jis").strip()),booklist)
        booklist = map((lambda x: x.rsplit("|")),booklist)
        booklist = map((lambda x: tuple(x)),booklist)

        self.BookDict = {}
        for x in booklist:
            name = x[0].strip()
            url = x[1].strip()
            self.BookDict[name] = url
        
        self.site_list = self.BookDict.keys()
        self.LBox.Set(self.site_list)

        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)


    def OnKeyChar(self,event):
        key = event.GetKeyCode()
        if key ==  wx.WXK_ESCAPE:
            wx.Exit()
        elif key == wx.WXK_UP:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() - 1
            if next >=  0:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(count - 1)
        
        elif key == wx.WXK_DOWN:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() + 1
            if next < count:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(0)

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            fr = self.LBox.GetStringSelection()
            webbrowser.open(self.BookDict[fr])
            wx.Exit()
        else: event.Skip()

    def OnText(self,event):
        word = self.TxtCtr.GetValue()
        isearch = IncrementalSearch(word,self.BookDict.keys())
        try:
            new_list = isearch.GetBackList()
        except:
            return False
        if new_list:
            self.LBox.Set(new_list)
            self.LBox.SetSelection(0)
        else: event.Skip()
        event.Skip()


class MyApp(wx.PySimpleApp): 
    def OnInit(self):
        self.TxtFrm = MyTxtFrm(None, -1)
        self.TxtFrm.SetSize( (180, 200) )
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()


        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            fr = self.LBox.GetStringSelection()
            webbrowser.open(self.BookDict[fr])
            wx.Exit()

Enterを押したときに、サイト名に対応したurlを開くようにします。

  1. 選択しているサイト名をキーにして、urlを取り出し
  2. それをデフォルトのブラウザで開く

ということをしてるわけですね。

使い方

登録はbookmark.iniを直接編集することで行います。

上下カーソルでの選択も、migemoでの絞り込みもできます。Enterでブックマークを開きます。Escで終了します。


まとめ

要は、AA管理ツールの枠組みを使えば、

  • 登録する辞書
  • Enterを押した時の挙動

の二つをいじるだけで、いろんなことができるというわけです。
他に僕が思いついたのは、定型文の管理。あと、辞書をうまく作ることができれば、クリップボード履歴を監視するeClipみたいなのも作れますね。

wxPythonでAA管理ツールを作ろう!第七回 直前のウィンドウに貼り付け

あいさつ

つかさです。
今回は、直前までアクティブだったウィンドウにAAを貼り付けられるようにします。

モジュールの導入

pyautoモジュールを入手しましょう。これは、Windowsの操作をカスタマイズ/自動化するためのモジュールです。
解凍したものを、スクリプトと同じフォルダにおきます。


スクリプト

  1. 新たにpyautoをインポートし
  2. Enterを押したときの挙動に「直前のウィンドウをアクティブにして」「貼り付け」を付け足してます
  • AAlist08.py
import wx,os,migemo,re,pyauto


migemo_object = None

class MyPopupWindow(wx.PopupWindow):
    def __init__(self, parent, style):
        wx.PopupWindow.__init__(self, parent, style)
        self.st = wx.StaticText(self, -1,pos=(10,10))

    def ChangeTxt(self,message,pos):
        
        self.st.SetLabel(message)
        sz = self.st.GetBestSize()
        gps = self.GetSize()
        self.SetDimensions(pos[0], pos[1], sz.width + 20 , sz.height + 20)
        self.Show(True)

class IncrementalSearch:
    def __init__(self,pattern,list):
        self.pattern = pattern
        self.new_list = []
        self.old_list = list

    def GetBackList(self):
        global migemo_object
        
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')
        re_pattern = migemo_object.query(self.pattern)
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False
                    
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list


class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id)
        
        aa_list = os.listdir("AAList")
        self.AA_Dict = {}
        for x in aa_list:
            key = os.path.splitext(x)[0].decode("shift-jis")
            path = os.path.join("AAlist",x)
            self.AA_Dict[key] = path

        self.win = MyPopupWindow(self,
                                 wx.SIMPLE_BORDER)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1, choices = self.AA_Dict.keys())
        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)


    def OnKeyChar(self,event):
        key = event.GetKeyCode()
        if key ==  wx.WXK_ESCAPE:
            wx.Exit()
        elif key == wx.WXK_UP:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() - 1
            if next >=  0:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(count - 1)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)
        
        elif key == wx.WXK_DOWN:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() + 1
            if next < count:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(0)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            c_board = wx.Clipboard()
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            c_board.SetData(wx.TextDataObject(fr))
            c_board.Flush()
            c_board.Close()
            pyauto.Input.send([
                pyauto.KeyDown(pyauto.VK_MENU ),
                pyauto.Key(pyauto.VK_ESCAPE ),
                pyauto.KeyUp(pyauto.VK_MENU),
                pyauto.KeyDown(pyauto.VK_CONTROL),
                pyauto.Key(ord('V')),
                pyauto.KeyUp(pyauto.VK_CONTROL)
            ])
            wx.Exit()
        else: event.Skip()

    def OnText(self,event):
        word = self.TxtCtr.GetValue()
        isearch = IncrementalSearch(word,self.AA_Dict.keys())
        try:
            new_list = isearch.GetBackList()
        except:
            return False
        if new_list:
            self.LBox.Set(new_list)
            self.LBox.SetSelection(0)
            self.ShowToolTip()
        else: event.Skip()
        event.Skip()
        

    def ShowToolTip(self):
        f = open(self.AA_Dict[self.LBox.GetStringSelection()])
        fr = f.read()
        
        gps = self.GetSize()
        gp = self.GetPosition()
        pos = (gp.x + gps.x, gp.y + 45)
        self.win.ChangeTxt(fr,pos)


class MyApp(wx.PySimpleApp): 
    def OnInit(self):

        self.TxtFrm = MyTxtFrm(None, -1)
        self.TxtFrm.SetSize( (180, 200) )
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()

キー操作

OnKeyCharの下の方を見てください。

            pyauto.Input.send([
                pyauto.KeyDown(pyauto.VK_MENU ),
                pyauto.Key(pyauto.VK_ESCAPE ),
                pyauto.KeyUp(pyauto.VK_MENU),
                pyauto.KeyDown(pyauto.VK_CONTROL),
                pyauto.Key(ord('V')),
                pyauto.KeyUp(pyauto.VK_CONTROL)
            ])
            wx.GetApp().OnClose()

Enterを押したときの動作に、数行加えています。
クリップボードにAAテキストを入れた後、

  1. 直前のウィンドウをアクティブにして
  2. 貼り付け

という動作を追加してます。

まず、直前のウインドウをアクティブに。これは、Alt+Escで実現できますね。Alt+Tabしか知らなかったひとは試してみましょう^^
次の貼り付けは、Ctrl+Vでできます。

pyauto.Input.sendで、それに対応したキーを送ります。

  1. Altキーを押して→Escapeキーを一瞬押して離して→Altキーを離してから
  2. Ctrlキーを押して→Vキーを一瞬押して離して→Ctrlキーを離す

という感じですね。

まとめ

これで、

  1. 直前にアクティブだったウィンドウをアクティブにし
  2. クリップボードに格納したものを貼り付け
  3. 終了する

という一連の動作が可能になりました。メイン部分ですることはもう無いかな?

一連の流れ画像

  • AAを貼り付けたいウィンドウの上で

  • Enterで貼り付け

  • よくできました

wxPythonでAA管理ツールを作ろう!第六回 PyMigemoでインクリメンタルサーチ

あいさつ

つかさです。
今回は、PyMigemoを使います。

正規表現について

まずは、python正規表現について。reモジュールを使うことで、正規表現が使えます。

  1. パターンをコンパイルし、正規表現オブジェクトを作る
  2. そのオブジェクトから、match()あるいはsearch()で、検索したい語を入れ、返り値を得る

という順序です。

PyMigemoを使うと、この正規表現のためのパターンを得ることができます。

PyMigemoのインストール

migemo.pydと、migemo.dllをスクリプトのあるフォルダにおけば、このモジュールを使えるようになります。
また、migemo用のDictもどこかからダウンロードしましょう。これも同じフォルダにおきます。


migemoでパターンを得る

例えば、Migemoオブジェクトを作った後、query()にtukaというのを与えると

([捕遺仕疲遣柄攫束塚使冢掴閊障把支捉司掌元曹搏]|tuka|tuka|つか|付かぬ事|ツカ)

このようなパターンを得ることができます。
このパターンを正規表現に利用すれば、ローマ字でも日本語を検索できるわけです。

プログラム

以前から変更したのは大きくは二点。

  1. IncrementalSearchクラスを付け加えた
  2. OnKeyTxtを付け加えた
  • AAlist07.py
import wx,os,migemo,re


migemo_object = None

class MyPopupWindow(wx.PopupWindow):
    def __init__(self, parent, style):
        wx.PopupWindow.__init__(self, parent, style)
        self.st = wx.StaticText(self, -1,pos=(10,10))

    def ChangeTxt(self,message,pos):
        
        self.st.SetLabel(message)
        sz = self.st.GetBestSize()
        gps = self.GetSize()
        self.SetDimensions(pos[0], pos[1], sz.width + 20 , sz.height + 20)
        self.Show(True)

class IncrementalSearch:
    def __init__(self,pattern,list):
        self.pattern = pattern
        self.new_list = []
        self.old_list = list

    def GetBackList(self):
        global migemo_object
        
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')
        re_pattern = migemo_object.query(self.pattern)
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False
                    
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list


class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id)
        
        aa_list = os.listdir("AAList")
        self.AA_Dict = {}
        for x in aa_list:
            key = os.path.splitext(x)[0].decode("shift-jis")
            path = os.path.join("AAlist",x)
            self.AA_Dict[key] = path

        self.win = MyPopupWindow(self,
                                 wx.SIMPLE_BORDER)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1, choices = self.AA_Dict.keys())
        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)


    def OnKeyChar(self,event):
        key = event.GetKeyCode()
        if key ==  wx.WXK_ESCAPE:
            wx.Exit()
        elif key == wx.WXK_UP:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() - 1
            if next >=  0:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(count - 1)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)
        
        elif key == wx.WXK_DOWN:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() + 1
            if next < count:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(0)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            c_board = wx.Clipboard()
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            c_board.SetData(wx.TextDataObject(fr))
            c_board.Flush()
            c_board.Close()
            wx.Exit()
        else: event.Skip()

    def OnText(self,event):
        word = self.TxtCtr.GetValue()
        isearch = IncrementalSearch(word,self.AA_Dict.keys())
        try:
            new_list = isearch.GetBackList()
        except:
            return False
        if new_list:
            self.LBox.Set(new_list)
            self.LBox.SetSelection(0)
            self.ShowToolTip()
        else: event.Skip()
        event.Skip()
        

    def ShowToolTip(self):
        f = open(self.AA_Dict[self.LBox.GetStringSelection()])
        fr = f.read()
        
        gps = self.GetSize()
        gp = self.GetPosition()
        pos = (gp.x + gps.x, gp.y + 45)
        self.win.ChangeTxt(fr,pos)


class MyApp(wx.PySimpleApp): 
    def OnInit(self):

        self.TxtFrm = MyTxtFrm(None, -1)
        self.TxtFrm.SetSize( (180, 200) )
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()


IncrementalSearchクラス

検索文字列と調べたいリストを受け取り、検索文字列に一致したもののみのリストを返すIncrementalSearchクラスを作製しましょう。

class IncrementalSearch:
    def __init__(self,pattern,list):
        self.pattern = pattern
        self.new_list = []
        self.old_list = list

    def GetBackList(self):
        global migemo_object
        
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')
        re_pattern = migemo_object.query(self.pattern)
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False
                    
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list

__init__のところを見てください。引数として

  • 検索に用いたい文字列
  • その文字列で検索したいリスト

を受け取ります。

GetBackListは、受け取ったリストを受け取った文字列でmigemo検索し、それにヒットした要素のみを、新しいリストとして返す関数です。GetBackListについて説明します。

Migemoオブジェクトの作成
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')

まず、Migemoオブジェクトがあるかどうかで分岐します。無い場合は、作製します。
一々オブジェクトを作ると、時間がかかるのでこのようにしています。

検索パターンの取得とコンパイル
        re_pattern = migemo_object.query(self.pattern)
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False

migemoオブジェクトに、引数として受け取ったエディットボックスに入力された文字を入れ、正規表現用のパターンを取得します。
その後、それをコンパイルします。

一致したリストを返す
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list

ついで、引数として取得したリストの一々の要素について、それがさきに作った正規表現パターンに一致するかを調べていきます。もし一致したら、それを新しいリストに加えます。
こうやって、古いリストから正規表現に一致したリストを新しく作り直すわけですね。
このようにして出来た新しいリストを、returnで返します。

本体と結びつける

OnText関数

エディットボックスで何か入力されるたびにこのクラスを呼び出し、リストを受け取り、ListBoxにセットすればいいわけですね。
そのための関数OnTextを作製します。

    def OnText(self,event):
        word = self.TxtCtr.GetValue()
        isearch = IncrementalSearch(word,self.AA_Dict.keys())
        try:
            new_list = isearch.GetBackList()
        except:
            return False
        if new_list:
            self.LBox.Set(new_list)
            self.LBox.SetSelection(0)
            self.ShowToolTip()
        else: event.Skip()
        event.Skip()

GetValue()でエディットボックスの文字列を受け取ります。
次に、先に作ったIncrementalSearchにその文字列と、ファイル名のリストを投げます。
そして戻ってきた新しいリストをListBoxにセットし、ListBoxの一番上を選択した状態にし、ツールチップを表示します。

EVT_TEXTで結びつけ

ついで、これをエディットボックスと結びつけます。class MyTxtFrmの初期化メソッド__init__に、次の一文を付け加えます。

        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)

これで、エディットボックスに文字が入力されるたびに、OnText関数が呼び出されることになります。

wxPythonでAA管理ツールを作ろう!第八回 設定ファイル

あいさつ

つかさです。
今回は設定ファイルです。ConfigParserというモジュールを使います。

設定が必要なもの

まずは設定ファイルを作成しましょう。

あたりが、必要なものでしょうか。
以下のファイルを、スクリプトのあるフォルダに保存してください。

  • aalist.ini
[DEFAULT]
backgroundcolour = #B0E0E6
width = 200
height = 250
x = 400
y = 300

この設定ファイルを読み込み、反映するようにスクリプトを改造します。

  • オブジェクトを作製
  • iniファイルを読み込み
  • read(セクション,値)で、個々の要素を取り出す

が一連の流れです。

スクリプト

ConfigParserというモジュールをインポートしてます。

  • AAlist09.py
import wx,os,migemo,re,pyauto,ConfigParser


migemo_object = None

class MyPopupWindow(wx.PopupWindow):
    def __init__(self, parent, style, ini):
        wx.PopupWindow.__init__(self, parent, style)
        
        self.ini = ini
        b_color = self.ini.get( "DEFAULT", "BackgroundColour" )
        self.SetBackgroundColour(b_color)

        self.st = wx.StaticText(self, -1,pos=(10,10))

    def ChangeTxt(self,message,pos):
        
        self.st.SetLabel(message)
        sz = self.st.GetBestSize()
        gps = self.GetSize()
        self.SetDimensions(pos[0], pos[1], sz.width + 20 , sz.height + 20)
        self.Show(True)

class IncrementalSearch:
    def __init__(self,pattern,list):
        self.pattern = pattern
        self.new_list = []
        self.old_list = list

    def GetBackList(self):
        global migemo_object
        
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')
        re_pattern = migemo_object.query(self.pattern)
        print re_pattern
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False
                    
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list


class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id, ini):
        wx.Frame.__init__(self, parent, id)        
        aa_list = os.listdir("AAList")
        self.AA_Dict = {}
        for x in aa_list:
            key = os.path.splitext(x)[0].decode("shift-jis")
            path = os.path.join("AAlist",x)
            self.AA_Dict[key] = path

        self.win = MyPopupWindow(self,
                                 wx.SIMPLE_BORDER,
                                 ini)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1, choices = self.AA_Dict.keys())
        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)


    def OnKeyChar(self,event):
        key = event.GetKeyCode()
        if key ==  wx.WXK_ESCAPE:
            wx.Exit()
        elif key == wx.WXK_UP:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() - 1
            if next >=  0:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(count - 1)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)
        
        elif key == wx.WXK_DOWN:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() + 1
            if next < count:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(0)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            c_board = wx.Clipboard()
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            c_board.SetData(wx.TextDataObject(fr))
            c_board.Flush()
            c_board.Close()
            pyauto.Input.send([
                pyauto.KeyDown(pyauto.VK_MENU ),
                pyauto.Key(pyauto.VK_ESCAPE ),
                pyauto.KeyUp(pyauto.VK_MENU),
                pyauto.KeyDown(pyauto.VK_CONTROL),
                pyauto.Key(ord('V')),
                pyauto.KeyUp(pyauto.VK_CONTROL)
            ])
            wx.Exit()
        else: event.Skip()

    def OnText(self,event):
        word = self.TxtCtr.GetValue()
        isearch = IncrementalSearch(word,self.AA_Dict.keys())
        try:
            new_list = isearch.GetBackList()
        except:
            return False
        if new_list:
            self.LBox.Set(new_list)
            self.LBox.SetSelection(0)
            self.ShowToolTip()
        else: event.Skip()
        event.Skip()
        

    def ShowToolTip(self):
        f = open(self.AA_Dict[self.LBox.GetStringSelection()])
        fr = f.read()
        
        gps = self.GetSize()
        gp = self.GetPosition()
        pos = (gp.x + gps.x, gp.y + 45)
        self.win.ChangeTxt(fr,pos)


class MyApp(wx.PySimpleApp): 
    def OnInit(self):

        self.INI_FILE = "aalist.ini"
        self.INI = ConfigParser.SafeConfigParser()
        self.INI.read(self.INI_FILE)


        self.width = self.INI.getint( "DEFAULT", "width" )
        self.height = self.INI.getint( "DEFAULT", "height" )
        self.x = self.INI.getint( "DEFAULT", "x" )
        self.y = self.INI.getint( "DEFAULT", "y" )
        

        self.TxtFrm = MyTxtFrm(None, -1, self.INI)        
        self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height)
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()


ウィンドウの位置と大きさ

class MyApp(wx.PySimpleApp): 
    def OnInit(self):

        self.INI_FILE = "aalist.ini"
        self.INI = ConfigParser.SafeConfigParser()
        self.INI.read(self.INI_FILE)

        self.width = self.INI.getint( "DEFAULT", "width" )
        self.height = self.INI.getint( "DEFAULT", "height" )
        self.x = self.INI.getint( "DEFAULT", "x" )
        self.y = self.INI.getint( "DEFAULT", "y" )
        
        self.TxtFrm = MyTxtFrm(None, -1, self.INI)        
        self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height)
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

MyAppの初期化の際に、

  1. 設定ファイルオブジェクトを作り
  2. 位置と大きさの値を取り出し
  3. TxtFrmに設定ファイルオブジェクトを引数として与える

ということをしてます。

        self.INI_FILE = "aalist.ini"
        self.INI = ConfigParser.SafeConfigParser()
        self.INI.read(self.INI_FILE)

最初の三行で、ConfigParser.SafeConfigParser()でオブジェクトを作り、iniファイルを読み込ませてます。

        self.width = self.INI.getint( "DEFAULT", "width" )
        self.height = self.INI.getint( "DEFAULT", "height" )
        self.x = self.INI.getint( "DEFAULT", "x" )
        self.y = self.INI.getint( "DEFAULT", "y" )

次に、getintでそのオブジェクトから必要な値を取り出してます。

  • 数字を取り出すならgetint
  • 文字列を取り出すならget

です。

        self.TxtFrm = MyTxtFrm(None, -1, self.INI)        
        self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height)

そしてSetDimensionsで、ウィンドウを取り出した位置と大きさにセットしてるわけですね。
また、MyTxtFrmの引数としてself.INIを与えているのにも注意してください。

他のクラスでオブジェクトを利用

ツールチップ表示のためには、別のクラスでもINIファイルを読み込まなくてはいけません。ですが一々別のクラスでも、一々同じようにオブジェクトを作って、というのは面倒ですね。

そこで、一度作ったiniオブジェクトを、引数として各クラスに渡すようにしてます。

  1. MyFrmでオブジェクトを作り
  2. それをMyTxtFrmに引数として与え
  3. さらにMyTxtFrmからMyPopupWindowにオブジェクトを引数として与える

ということをしてます。

位置の記憶

終了時の大きさと位置を記憶し、起動時にはそこで表示したいという場合があると思います。それができるように、スクリプトを書き換えてみましょう。

その場合は、

  1. 終了する直前にiniオブジェクトを呼び出し
  2. writeで書き込む

そして起動したときには

  1. iniでその箇所を読み込む

というようにします。まずは設定ファイルを書き換えてください

  • aalist.ini
[DEFAULT]
backgroundcolour = #B0E0E6
width = 200
height = 250
x = 400
y = 300
historymode = 1

[HISTORY]
width = 188
height = 238
x = 254
y = 278

DEFAULTセクションに、位置や大きさを記録するかどうかを決められるようhistorymodeを付け足してます。これが0なら記憶しない。1なら記憶するようにします。

スクリプト

MyAppの初期化のところで、前回の位置や記録を読み込むかどうかで分岐させてます
終了時に位置を記録するため、WriteIniとOnExitの二つの関数を付け足してます

  • AAlist10.py
import wx,os,migemo,re,pyauto,ConfigParser


migemo_object = None

class MyPopupWindow(wx.PopupWindow):
    def __init__(self, parent, style, ini):
        wx.PopupWindow.__init__(self, parent, style)
        
        self.ini = ini
        b_color = self.ini.get( "DEFAULT", "BackgroundColour" )
        self.SetBackgroundColour(b_color)

        self.st = wx.StaticText(self, -1,pos=(10,10))

    def ChangeTxt(self,message,pos):
        
        self.st.SetLabel(message)
        sz = self.st.GetBestSize()
        gps = self.GetSize()
        self.SetDimensions(pos[0], pos[1], sz.width + 20 , sz.height + 20)
        self.Show(True)

class IncrementalSearch:
    def __init__(self,pattern,list):
        self.pattern = pattern
        self.new_list = []
        self.old_list = list

    def GetBackList(self):
        global migemo_object
        
        if migemo_object==None:
            migemo_object = migemo.Migemo('Dict\migemo-dict')
        re_pattern = migemo_object.query(self.pattern)
        print re_pattern
        try:
            migemo_re_object = re.compile(re_pattern, re.IGNORECASE)
        except re.error:
            return False
                    
        for x in self.old_list:
            if migemo_re_object.search(x):
                self.new_list.append(x)
        return self.new_list


class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id, ini):
        wx.Frame.__init__(self, parent, id)        
        aa_list = os.listdir("AAList")
        self.AA_Dict = {}
        for x in aa_list:
            key = os.path.splitext(x)[0].decode("shift-jis")
            path = os.path.join("AAlist",x)
            self.AA_Dict[key] = path

        self.win = MyPopupWindow(self,
                                 wx.SIMPLE_BORDER,
                                 ini)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1, choices = self.AA_Dict.keys())
        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.TxtCtr.Bind(wx.EVT_TEXT,self.OnText)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)


    def OnKeyChar(self,event):
        key = event.GetKeyCode()
        if key ==  wx.WXK_ESCAPE:
            wx.GetApp().OnExit()
        elif key == wx.WXK_UP:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() - 1
            if next >=  0:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(count - 1)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)
        
        elif key == wx.WXK_DOWN:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() + 1
            if next < count:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(0)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            c_board = wx.Clipboard()
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            c_board.SetData(wx.TextDataObject(fr))
            c_board.Flush()
            c_board.Close()
            pyauto.Input.send([
                pyauto.KeyDown(pyauto.VK_MENU ),
                pyauto.Key(pyauto.VK_ESCAPE ),
                pyauto.KeyUp(pyauto.VK_MENU),
                pyauto.KeyDown(pyauto.VK_CONTROL),
                pyauto.Key(ord('V')),
                pyauto.KeyUp(pyauto.VK_CONTROL)
            ])
            wx.GetApp().OnExit()
        else: event.Skip()

    def OnText(self,event):
        word = self.TxtCtr.GetValue()
        isearch = IncrementalSearch(word,self.AA_Dict.keys())
        try:
            new_list = isearch.GetBackList()
        except:
            return False
        if new_list:
            self.LBox.Set(new_list)
            self.LBox.SetSelection(0)
            self.ShowToolTip()
        else: event.Skip()
        event.Skip()
        

    def ShowToolTip(self):
        f = open(self.AA_Dict[self.LBox.GetStringSelection()])
        fr = f.read()
        
        gps = self.GetSize()
        gp = self.GetPosition()
        pos = (gp.x + gps.x, gp.y + 45)
        self.win.ChangeTxt(fr,pos)


class MyApp(wx.PySimpleApp): 
    def OnInit(self):

        self.INI_FILE = "aalist.ini"
        self.INI = ConfigParser.SafeConfigParser()
        self.INI.read(self.INI_FILE)

        if self.INI.getint( "DEFAULT", "HistoryMode" ) == 1:
            self.width = self.INI.getint( "HISTORY", "Width" )
            self.height = self.INI.getint( "HISTORY", "Height" )
            self.x = self.INI.getint( "HISTORY", "X" )
            self.y = self.INI.getint( "HISTORY", "Y" )
        else:
            self.width = self.INI.getint( "DEFAULT", "Width" )
            self.height = self.INI.getint( "DEFAULT", "Height" )
            self.x = self.INI.getint( "DEFAULT", "X" )
            self.y = self.INI.getint( "DEFAULT", "Y" )
        

        self.TxtFrm = MyTxtFrm(None, -1, self.INI)        
        self.TxtFrm.SetDimensions(self.x, self.y, self.width, self.height)
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1
        

    def WriteINI(self):
        
        if self.INI.getint( "DEFAULT", "HistoryMode" ) == 1:
            x = str(self.TxtFrm.GetPosition()[0])
            y = str(self.TxtFrm.GetPosition()[1])
            width = str(self.TxtFrm.GetSize()[0])
            height = str(self.TxtFrm.GetSize()[1])
            self.INI.set('HISTORY','Width',width)
            self.INI.set('HISTORY','Height',height)
            self.INI.set('HISTORY','X',x)
            self.INI.set('HISTORY','Y',y)
            f = open(self.INI_FILE, "w")
            self.INI.write(f)
            f.close()
            
        else:
            return

    def OnExit(self):
        self.WriteINI()
        wx.Exit()

app = MyApp()
app.MainLoop()

前回の位置の読み込み

MyAppの初期化のところを見てください。

        if self.INI.getint( "DEFAULT", "HistoryMode" ) == 1:
            self.width = self.INI.getint( "HISTORY", "Width" )
            self.height = self.INI.getint( "HISTORY", "Height" )
            self.x = self.INI.getint( "HISTORY", "X" )
            self.y = self.INI.getint( "HISTORY", "Y" )
        else:
            self.width = self.INI.getint( "DEFAULT", "Width" )
            self.height = self.INI.getint( "DEFAULT", "Height" )
            self.x = self.INI.getint( "DEFAULT", "X" )
            self.y = self.INI.getint( "DEFAULT", "Y" )

前回の位置と大きさを読み込む設定になっていれば、HISTORYTセクションから読み込むように。なっていなければDEFAULTセクションで設定した値を読み込むようにしてます。

位置と大きさの記録

AAlist終了時には、OnExitを利用するようにします。AAlistを終了する時、というのは

  • Escapeキーを押したとき
  • Enterで貼り付けたとき

の二通りですね。それぞれ、今まではwx.Exit()で終了してたのを、wx.GetApp().OnExit()で新しく付け足した関数で終了するようにかえてます。

    def WriteINI(self):
        
        if self.INI.getint( "DEFAULT", "HistoryMode" ) == 1:
            x = str(self.TxtFrm.GetPosition()[0])
            y = str(self.TxtFrm.GetPosition()[1])
            width = str(self.TxtFrm.GetSize()[0])
            height = str(self.TxtFrm.GetSize()[1])
            self.INI.set('HISTORY','Width',width)
            self.INI.set('HISTORY','Height',height)
            self.INI.set('HISTORY','X',x)
            self.INI.set('HISTORY','Y',y)
            f = open(self.INI_FILE, "w")
            self.INI.write(f)
            f.close()
            
        else:
            return

    def OnExit(self):
        self.WriteINI()
        wx.Exit()

DEFAULTセクションのhistorymodeの値をチェックし、前回の位置や大きさを記憶する設定であれば

  1. 現在のウィンドウの位置と大きさを取り出し
  2. それをINIオブジェクトにセットし
  3. INIファイルに書き込む

ということをします。

AA管理ツール SETZER ver0.01 公開

あいさつ

AA管理ツールが一応完成したので、公開します。
現在連載している「wxPythonでAA管理ツールを作ろう!」シリーズでは、九回目あたりで到達するであろうソースを使ってます。
直前までアクティブだったウィンドウに、選択したAAを貼り付けます。

Download SETZER ver.0.01.zip
※最新版はhoehoeSoft

  • 操作
    • ウィンドウを閉じる→ESC
    • アイテム選択→カーソルキー
    • 選択アイテム貼り付け→Enter

Migemoを使いたいとき

dictディレクトリにMigemoの辞書ファイルを配置してください。

  • 辞書ファイル
    • han2zen.dat
    • hira2kata.dat
    • migemo-dict
    • roma2hira.dat

後は、SETZER.iniを編集しIsearchType = 1にすることで機能が有効になります。

wxPythonでAA管理ツールを作ろう!第五回 クリップボードに保存

あいさつ

つかさです。
今回は、クリップボードに選択したファイルの中身をコピーします。

クリップボード

MyTxtFrmクラスのOnKeyCharに、Enter用の分岐を付け加えてます。

  • AAlist06.py
import wx,os

class MyPopupWindow(wx.PopupWindow):
    def __init__(self, parent, style):
        wx.PopupWindow.__init__(self, parent, style)
        self.st = wx.StaticText(self, -1,pos=(10,10))

    def ChangeTxt(self,message,pos):
        
        self.st.SetLabel(message)
        sz = self.st.GetBestSize()
        gps = self.GetSize()
        self.SetDimensions(pos[0], pos[1], sz.width + 20 , sz.height + 20)
        self.Show(True)


class MyTxtFrm(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id)
        
        aa_list = os.listdir("AAList")
        self.AA_Dict = {}
        for x in aa_list:
            key = os.path.splitext(x)[0].decode("shift-jis")
            path = os.path.join("AAlist",x)
            self.AA_Dict[key] = path

        self.win = MyPopupWindow(self,
                                 wx.SIMPLE_BORDER)

        self.TxtCtr = wx.TextCtrl(self, -1)
        self.LBox = wx.ListBox(self, -1, choices = self.AA_Dict.keys())
        self.TxtCtr.Bind(wx.EVT_KEY_DOWN, self.OnKeyChar)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.TxtCtr, 0, wx.EXPAND)
        self.sizer.Add(self.LBox, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)


    def OnKeyChar(self,event):
        key = event.GetKeyCode()
        if key ==  wx.WXK_ESCAPE:
            wx.Exit()
        elif key == wx.WXK_UP:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() - 1
            if next >=  0:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(count - 1)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)
        
        elif key == wx.WXK_DOWN:
            count = self.LBox.GetCount()
            next = self.LBox.GetSelection() + 1
            if next < count:
                self.LBox.SetSelection(next)
            else: self.LBox.SetSelection(0)
            
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            
            gps = self.GetSize()
            gp = self.GetPosition()
            pos = (gp.x + gps.x, gp.y + 45)
            self.win.ChangeTxt(fr,pos)

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            c_board = wx.Clipboard()
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            c_board.SetData(wx.TextDataObject(fr))
            c_board.Flush()
            c_board.Close()
            wx.Exit()
        else: event.Skip()

class MyApp(wx.PySimpleApp): 
    def OnInit(self):

        self.TxtFrm = MyTxtFrm(None, -1)
        self.TxtFrm.SetSize( (180, 200) )
        self.TxtFrm.Show()
        self.TxtFrm.TxtCtr.SetFocus()
        return 1

app = MyApp()
app.MainLoop()


Enterを押したときの分岐

Enterを押せば、クリップボードに選択したファイルの中身をコピーし、終了するようにします。
Charの分岐にEnterを付け加えます。

        elif key in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            c_board = wx.Clipboard()
            f = open(self.AA_Dict[self.LBox.GetStringSelection()])
            fr = f.read()
            c_board.SetData(wx.TextDataObject(fr))
            c_board.Flush()
            c_board.Close()
            wx.Exit()
        else: event.Skip()

この箇所ですね。ListBoxで選択してるファイル名に対応したパスを、辞書を利用して取得し、その中身を取り出してクリップボードにセットしてます。
その後に、wx.Exit()でプログラムを終了しています。

次回の予定

これで、とりあえずはAA管理ツールとして一応は完成した、といってもいいのではないでしょうか。
次回はMigemoインクリメンタルサーチができるようにする予定です