wxPythonでAA管理ツールを作ろう!第四回 ツールチップ表示

あいさつ

つかさです。
今回は、リストボックスで選択している箇所の内容をツールチップ表示できるようにします。

前回からの変更点

ツールチップ表示用に、新しくMyPopUpWindowクラスを作成してます。
ListBoxで選択カーソルが移動すれば、ツールチップの表示内容が変化するようにしてます。

  • AAlist05.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)
        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()


MyPopUpWindowクラスの作成

MyPopupWindowが、今回新しく付け加えたクラスです。ツールチップを表示し、操作するためのクラスです。

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)

初期化メソッドの方は単純ですね。スタティックテキストをセットしているだけです。
ChangeTxt関数は、引数として表示する文字列と、ポジションとを受け取ります。

  1. 引数で与えられたメッセージを、SetLabelでStaticTextに貼り付けます。
  2. ついで、GetBestSize()でそのメッセージにあうツールチップの大きさの値を返します。
  3. SetDimensions()は、大きさと位置を指定する関数です。引数として受け取ったposから位置を。GetBestSize()で得た値から適切なサイズをセットしてます。
  4. Show(True)でツールチップを表示します

OnKeyChar

カーソルを上下すれば、それに併せてツールチップが表示されるようにします。OnKeyCharに数行付け加えます。

        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)

下半分が今回付け加えた箇所ですね。

ファイル内容の取得
            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)

ここではツールチップを表示する位置を取得してます。取得したい位置は、ちょうど○をつけたあたり。

この位置を計算するために、現在のGUIの位置と、GUIの幅が必要になるわけですね。
GUIの位置をGetPosition()で。GUIの大きさをGetSize()で取得。ここから適切なポジションを割り出します。


ChangeTxtにファイル内容と表示位置を渡す
            self.win.ChangeTxt(fr,pos)

そして最後の行で、ここまでで取得した、カーソル位置に対応しているファイルの中身と、ポジションとをMyPopUpWindowクラスのChangeTxt関数に送っているわけです。

これで、カーソルを上下すれば、それに併せてGUIの横に、その中身を表示するツールチップを表示することができるようになりました。