This recipe generates a dynamic icon (2 vertical, 5 segment bar graphs) in the system tray.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import wx
import string
import sys
ID_ICON_TIMER = wx.NewId()
##
# The IconBar class
#
class IconBar:
##
# \brief the constructor default left: red, default right: green
#
def __init__(self,l_off=[128,0,0],l_on=[255,0,0],r_off=[0,128,0],r_on=[0,255,0]):
self.s_line = "\xff\xff\xff"+"\0"*45
self.s_border = "\xff\xff\xff\0\0\0"
self.s_point = "\0"*3
self.sl_off = string.join(map(chr,l_off),'')*6
self.sl_on = string.join(map(chr,l_on),'')*6
self.sr_off = string.join(map(chr,r_off),'')*6
self.sr_on = string.join(map(chr,r_on),'')*6
##
# \brief gets a new icon with 0 <= l,r <= 5
#
def Get(self,l,r):
s=""+self.s_line
for i in range(5):
if i<(5-l):
sl = self.sl_off
else:
sl = self.sl_on
if i<(5-r):
sr = self.sr_off
else:
sr = self.sr_on
s+=self.s_border+sl+self.s_point+sr+self.s_point
s+=self.s_border+sl+self.s_point+sr+self.s_point
s+=self.s_line
image = wx.EmptyImage(16,16)
image.SetData(s)
bmp = image.ConvertToBitmap()
bmp.SetMask(wx.Mask(bmp, wx.WHITE)) #sets the transparency colour to white
icon = wx.EmptyIcon()
icon.CopyFromBitmap(bmp)
return icon
##
# The TaskBarIcon class
#
class MyTaskBarIcon(wx.TaskBarIcon):
l = 0
r = 0
##
# \brief the constructor
#
def __init__(self, frame):
wx.TaskBarIcon.__init__(self)
self.frame = frame
self.IconBar = IconBar((127,127,0),(255,255,0),(0,127,127),(0,255,255))
self.SetIconBar(self.l,self.r)
##
# \brief sets the icon timer
#
def SetIconTimer(self):
self.icon_timer = wx.Timer(self, ID_ICON_TIMER)
wx.EVT_TIMER(self, ID_ICON_TIMER, self.BlinkIcon)
self.icon_timer.Start(100)
##
# \brief blinks the icon and updates self.l and self.r
#
def BlinkIcon(self, event):
self.SetIconBar(self.l,self.r)
self.l += 1
if self.l > 5:
self.l = 0
self.r += 1
if self.r > 5:
self.r = 0
##
# \brief sets the icon bar and a message
#
def SetIconBar(self,l,r):
icon = self.IconBar.Get(l,r)
self.SetIcon(icon, "L:%d,R:%d"%(l,r))
##
# The task bar application
#
class TaskBarApp(wx.Frame):
##
# \brief the constructor
#
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, -1, title, size = (1, 1),
style=wx.FRAME_NO_TASKBAR|wx.NO_FULL_REPAINT_ON_RESIZE)
self.tbicon = MyTaskBarIcon(self)
self.tbicon.SetIconTimer()
self.Show(True)
##
# The main application wx.App class
#
class MyApp(wx.App):
def OnInit(self):
frame = TaskBarApp(None, -1, ' ')
frame.Center(wx.BOTH)
frame.Show(False)
return True
def main(argv=None):
if argv is None:
argv = sys.argv
app = MyApp(0)
app.MainLoop()
if __name__ == '__main__':
main()
|
Two things I found a bit of a bother:
wx.Icon doesn't expose the SetData() method, so the only way is to generate an image, then convert it to a bitmap then to an icon.
Windows insists on the icons being 16x16. If your icon is somewhat smaller than that (like mine was 15x16) you will need to pad it with a transparent colour.
The trick is to select a colour you will use for transparency, white in my case. then do image = wx.EmptyImage(16,16) image.SetData(s) bmp = image.ConvertToBitmap() bmp.SetMask(wx.Mask(bmp, wx.WHITE)) #sets the transparency colour to white icon = wx.EmptyIcon() icon.CopyFromBitmap(bmp)
The SetMask() makes the bitmap transparent where the pixels are white. Good news is, transparency is also transferred to the icon.
Nice. Thank you very much for this piece of code.