Aqua風ボタンにしてみる

しばらくぶりにwxPythonのデモを見たら、結構機能が増えていることに気付く。電子掲示版に見られるように、文字列を横に流して表示すること(Ticker)も普通にできるようになっていた。どう実装するのか悩んだのが遠い昔のようだ。1年前ぐらいか?もしかしたらその時にも、すでにTickerが使えたのかな?
今回は、Aqua風ボタンを表示するデモのAquaButton.pyを詳しく見てみる。ただのボタンよりもきれいだから。あんまりボタンだけ凝り過ぎても、全体からしたら浮いてしまうこともあるので、ピンポイントで凝り過ぎるのは注意が必要だ。

AquaButton.pyのオリジナル画面は下のようになる。

ボタンが二つあってどちらもAqua風なのだが、上のボタンはクリックすると明減する。下のボタンは、マウスがボタン上に来るとボタンの色が変化する。
ソースコードを部分的に見ていく。

boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
boldFont.SetWeight(wx.BOLD)

for child in self.mainPanel.GetChildren():
    if isinstance(child, wx.StaticText):
        child.SetFont(boldFont)

この部分では単にフォントを決めてるだけなのだろうが、見慣れないことをしている。表示されるのは、太字だけれどもデフォルトのフォントのように見えるのだが...。ここで全部の画面のフォントを決めているだけ、とか。

def OnPulse(self, event):
    self.btn1.SetPulseOnFocus(event.IsChecked())

メソッドSetPulseOnFocusを使うと、ボタンを押すとボタンが明減するようになる。他のボタンを押すとこの点滅は止まるが、何もしない限り明減し続ける。こうすると見た目はきれいになるが、Windows以外での挙動が不明なのでこれ以上掘り下げるのは止める。マウスがボタン上にあるときに、ボタンの色が変わる方がシンプルでよい。

self.btn1.SetBackgroundColour(wx.Colour(255,255,100))
self.btn1.SetHoverColour(wx.Colour(255,0,000))
self.btn1.SetForegroundColour(wx.Colour(0,0,0))

このように、ボタンの色を直接指定するようにした。HoverColourが、マウスがボタン上にあるときのボタンの色を与える。ForegroundColourは何を指定してもどこにも影響がないように見える。黒(0,0,0)にしてもどこかが真っ黒になるわけでもないし。

コードをシンプルにするために、余計な部分を削って下のようにした。

import wx
import os
import sys

bitmapDir = os.getcwd()

try:
    from agw import aquabutton as AB
except ImportError:
    import wx.lib.agw.aquabutton as AB
            
class AquaButtonDemo(wx.Frame):
    def __init__(self):
        width, height = 150, 170
        wx.Frame.__init__(self, None, title='test',
                          size=wx.Size(width, height))
        self.mainPanel = wx.Panel(self)
        self.mainPanel.SetBackgroundColour(wx.WHITE)
        
        bitmap = wx.Bitmap(
            os.path.normpath(os.path.join(bitmapDir, "aquabutton.png")), 
            wx.BITMAP_TYPE_PNG)
        self.btn1 = AB.AquaButton(self.mainPanel, -1, bitmap, 'button')
        self.btn1.SetBackgroundColour(wx.Colour(000,000,255))
        self.btn1.SetHoverColour(wx.Colour(0,255,255))
        self.btn1.SetForegroundColour(wx.Colour(0,0,0))
        self.btn2 = AB.AquaButton(self.mainPanel, -1, bitmap, 'button')
        self.btn2.SetBackgroundColour(wx.Colour(000,000,255))
        self.btn2.SetHoverColour(wx.Colour(0,255,255))
        self.btn2.SetForegroundColour(wx.Colour(0,0,0))

        self.DoLayout()
        self.BindEvents() 

    def DoLayout(self):
        mainSizer = wx.BoxSizer(wx.VERTICAL)        
        mainSizer.Add(self.btn1, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        mainSizer.Add(self.btn2, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        self.mainPanel.SetSizer(mainSizer)
        mainSizer.Layout()

    def BindEvents(self):
        self.Bind(wx.EVT_BUTTON, self.OnButton1, self.btn1)
        self.Bind(wx.EVT_BUTTON, self.OnButton1, self.btn2) 
            
    def OnButton1(self, event):
        obj = event.GetEventObject()

class Application(wx.App):
    def OnInit(self):
        frame = AquaButtonDemo()
        frame.Show(True)
        self.SetTopWindow(frame)
        return True
        
def main():
    app = Application(0)
    app.MainLoop()

if __name__ == '__main__':
    main()

このコードでの起動画面は次の通り。

上のボタンにマウスを重ねたときの様子。