wxPythonでAA管理ツールを作ろう!第八回 設定ファイル
あいさつ
つかさです。
今回は設定ファイルです。ConfigParserというモジュールを使います。
設定が必要なもの
まずは設定ファイルを作成しましょう。
- 大きさ(幅と高さ)
- 位置(x,y)
- ツールチップの色
あたりが、必要なものでしょうか。
以下のファイルを、スクリプトのあるフォルダに保存してください。
- 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の初期化の際に、
- 設定ファイルオブジェクトを作り
- 位置と大きさの値を取り出し
- 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オブジェクトを、引数として各クラスに渡すようにしてます。
- MyFrmでオブジェクトを作り
- それをMyTxtFrmに引数として与え
- さらにMyTxtFrmからMyPopupWindowにオブジェクトを引数として与える
ということをしてます。
位置の記憶
終了時の大きさと位置を記憶し、起動時にはそこで表示したいという場合があると思います。それができるように、スクリプトを書き換えてみましょう。
その場合は、
- 終了する直前にiniオブジェクトを呼び出し
- writeで書き込む
そして起動したときには
- 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の値をチェックし、前回の位置や大きさを記憶する設定であれば
- 現在のウィンドウの位置と大きさを取り出し
- それをINIオブジェクトにセットし
- INIファイルに書き込む
ということをします。