WxPython改变了位图按钮的形状

时间:2011-06-23 05:27:20

标签: python wxpython

嗨,我对wxPython很新,还在学习的过程中。我正在尝试使用这样的特定图像制作位图按钮,例如:http://i.min.us/idk3Uy.png

我想在按钮中保留图像的原始形状,例如圆形按钮,而不是矩形按钮(默认情况下)。

我想知道如何做到这一点,或者是否有可能做到这一点;我确实看了一下文档,我发现样式常量wx.BU_EXACTFIT删除了不必要的边框......但是它仍然不是我希望它的理想形状。

感谢。

1 个答案:

答案 0 :(得分:15)

您可能需要为此实现自定义控件。我已经完成了自己的自定义wxPython控件,所以我继续为你写了一个ShapedButton类。 =)

要运行此演示,您只需要三张图片:

  • 按钮-normal.png
  • 按钮-pressed.png
  • 按钮-disabled.png

根据按钮的状态使用三个图像。只需要“正常”,但您可能希望至少提供“正常”和“按下”,以便用户在点击时获得反馈。

控件仅响应正常位图的非透明区域中的点击。单击并释放时,它会正确触发EVT_BUTTON事件。

享受!

Demo Screenshot

import wx

class ShapedButton(wx.PyControl):
    def __init__(self, parent, normal, pressed=None, disabled=None):
        super(ShapedButton, self).__init__(parent, -1, style=wx.BORDER_NONE)
        self.normal = normal
        self.pressed = pressed
        self.disabled = disabled
        self.region = wx.RegionFromBitmapColour(normal, wx.Color(0, 0, 0, 0))
        self._clicked = False
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.Bind(wx.EVT_SIZE, self.on_size)
        self.Bind(wx.EVT_PAINT, self.on_paint)
        self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
        self.Bind(wx.EVT_LEFT_DCLICK, self.on_left_dclick)
        self.Bind(wx.EVT_LEFT_UP, self.on_left_up)
        self.Bind(wx.EVT_MOTION, self.on_motion)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.on_leave_window)
    def DoGetBestSize(self):
        return self.normal.GetSize()
    def Enable(self, *args, **kwargs):
        super(ShapedButton, self).Enable(*args, **kwargs)
        self.Refresh()
    def Disable(self, *args, **kwargs):
        super(ShapedButton, self).Disable(*args, **kwargs)
        self.Refresh()
    def post_event(self):
        event = wx.CommandEvent()
        event.SetEventObject(self)
        event.SetEventType(wx.EVT_BUTTON.typeId)
        wx.PostEvent(self, event)
    def on_size(self, event):
        event.Skip()
        self.Refresh()
    def on_paint(self, event):
        dc = wx.AutoBufferedPaintDC(self)
        dc.SetBackground(wx.Brush(self.GetParent().GetBackgroundColour()))
        dc.Clear()
        bitmap = self.normal
        if self.clicked:
            bitmap = self.pressed or bitmap
        if not self.IsEnabled():
            bitmap = self.disabled or bitmap
        dc.DrawBitmap(bitmap, 0, 0)
    def set_clicked(self, clicked):
        if clicked != self._clicked:
            self._clicked = clicked
            self.Refresh()
    def get_clicked(self):
        return self._clicked
    clicked = property(get_clicked, set_clicked)
    def on_left_down(self, event):
        x, y = event.GetPosition()
        if self.region.Contains(x, y):
            self.clicked = True
    def on_left_dclick(self, event):
        self.on_left_down(event)
    def on_left_up(self, event):
        if self.clicked:
            x, y = event.GetPosition()
            if self.region.Contains(x, y):
                self.post_event()
        self.clicked = False
    def on_motion(self, event):
        if self.clicked:
            x, y = event.GetPosition()
            if not self.region.Contains(x, y):
                self.clicked = False
    def on_leave_window(self, event):
        self.clicked = False

def main():
    def on_button(event):
        print 'Button was clicked.'
    app = wx.PySimpleApp()
    frame = wx.Frame(None, -1, 'Shaped Button Demo')
    panel = wx.Panel(frame, -1)
    button = ShapedButton(panel, 
        wx.Bitmap('button-normal.png'), 
        wx.Bitmap('button-pressed.png'), 
        wx.Bitmap('button-disabled.png'))
    button.Bind(wx.EVT_BUTTON, on_button)
    sizer = wx.BoxSizer(wx.VERTICAL)
    sizer.AddStretchSpacer(1)
    sizer.Add(button, 0, wx.ALIGN_CENTER)
    sizer.AddStretchSpacer(1)
    panel.SetSizer(sizer)
    frame.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()