Search code examples
pythonimagewxpythonwxwidgetshover

How to create hover effect on StaticBitmap in wxpython?


I want to create hover effect on StaticBitmap - If the cursor of mouse is over the the bitmap, shows one image, if not, shows second image. It's trivial program (works perfectly with a button). However, StaticBitmap doesn't emit EVT_WINDOW_ENTER, EVT_WINDOW_LEAVE events.

I can work with EVT_MOTION. If images are switched when the cursor is on the edge of image, switch sometimes doesn't work. (Mainly with fast moving over the edge).

Example code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

def onWindow(event):
    print "window event:", event.m_x, event.m_y

def onMotion(event):
    print "motion event:", event.m_x, event.m_y

app = wx.App()

imageA = wx.Image("b.gif", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
imageB = wx.Image("a.gif", wx.BITMAP_TYPE_ANY).ConvertToBitmap()

frame = wx.Frame(None, wx.ID_ANY, title="Hover effect", size=(100+imageA.GetWidth(), 100+imageA.GetHeight()))

w = wx.Window(frame)
bmp = wx.StaticBitmap(w, -1, imageA, (50, 50), (imageA.GetWidth(), imageA.GetHeight()))
bmp.Bind(wx.EVT_MOTION, onMotion) 
bmp.Bind(wx.EVT_ENTER_WINDOW, onWindow)
bmp.Bind(wx.EVT_LEAVE_WINDOW, onWindow)

frame.Show()
app.MainLoop()

Solution

  • It looks like this is a wxGTK bug, ENTER and LEAVE events work fine on windows. You should direct the attention of the core developers to the problem, a good place to do this is their bug tracker. This is an issue you should not have to work around IMHO.

    I have found that GenericButtons do not have this problem on wxGTK, so maybe you can use that until StaticBitmap gets fixed.

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import wx
    from wx.lib import buttons
    
    def onWindow(event):
        print "window event:", event.m_x, event.m_y
    
    def onMotion(event):
        print "motion event:", event.m_x, event.m_y
    
    app = wx.App()
    
    imageA = wx.Image("b.gif", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
    imageB = wx.Image("a.gif", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
    
    frame = wx.Frame(None, wx.ID_ANY, title="Hover effect", size=(100+imageA.GetWidth(), 100+imageA.GetHeight()))
    
    w = wx.Window(frame)
    #bmp = wx.StaticBitmap(w, -1, imageA, (50, 50), (imageA.GetWidth(), imageA.GetHeight()))
    bmp = buttons.GenBitmapButton(w, -1, imageA, style=wx.BORDER_NONE)
    #bmp.Bind(wx.EVT_MOTION, onMotion)
    bmp.Bind(wx.EVT_ENTER_WINDOW, onWindow)
    bmp.Bind(wx.EVT_LEAVE_WINDOW, onWindow)
    
    frame.Show()
    app.MainLoop()