WxPython改变位图按钮的形状

发布于 2024-11-16 18:51:59 字数 298 浏览 0 评论 0原文

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

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

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

谢谢。

Hi I'm sort new to wxPython and still in the process of learning. I'm trying to make a bitmap button using a particular image like this for example: http://i.min.us/idk3Uy.png

The catch is I want to retain the original shape of the image in the button, like a circular button for example instead of a rectangular one (which is default).

I want to know how to do that exactly or if it is possible to do that at all; I did take a look at the documentation and I've found the style constant wx.BU_EXACTFIT removes the unnecessary borders...but it's still not in the desirable shape that I want it to be.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

神仙妹妹 2024-11-23 18:51:59

您可能必须为此实现自定义控件。我已经完成了相当多的自定义 wxPython 控件,因此我继续为您编写了一个 ShapedButton 类。 =)

要运行此演示,您只需要三个图像:

  • button-normal.pngbutton
  • -pressed.pngbutton
  • -disabled.png

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

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

享受!

演示屏幕截图

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()

You're probably going to have to implement a custom control for this. I've done my fair share of custom wxPython controls, so I went ahead and wrote a ShapedButton class for you. =)

To run this demo, you just need three images:

  • button-normal.png
  • button-pressed.png
  • button-disabled.png

The three images are used depending on the state of the button. Only the "normal" one is required, but you probably want to at least provide "normal" and "pressed" so the user gets feedback when clicking.

The control only responds to clicks in non-transparent areas of the normal bitmap. It properly fires the EVT_BUTTON event when clicked and released.

Enjoy!

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文