如何使用wxpython在图标(而非位图)上绘制不透明文本



简短问题

我知道如何在wx上绘制文本。位图,但是如何在wx上绘制文本。wxpython中的图标,使其看起来不透明

长问题:

我有一个基于wxpython的GUI应用程序,它有一个任务栏图标,我使用mytaskbaricon.SetIcon("myicon.ico")设置它。

现在我想在图标上动态地放置一些文本,所以我尝试使用这里解释的wx-.DrawText方法。如果我对位图(在菜单项中使用)进行测试,这会很好。

但是,任务栏需要wxIcon而不是wxBitmap。所以我想我会把图标转换成位图,画出文本,然后把它转换回图标。这是有效的,除了文本是

不显示透明。为什么?如何使文本不透明?

我的代码大致如下:

import wx
class MyTaskBarIcon(wx.TaskBarIcon):
  ...
  icon = wx.Icon("myicon.ico", wx.BITMAP_TYPE_ICO)
  bmp = wx.Bitmap("myicon.ico", wx.BITMAP_TYPE_ICO)
  memDC = wx.MemoryDC()
  memDC.SetTextForeground(wx.RED)
  memDC.SelectObject(bmp)
  memDC.DrawText("A", 0, 0)
  icon.CopyFromBitmap(bmp)
  self.SetIcon(icon, APP_NAME_WITH_VERSION)
  ...

因此,没有出现任何错误,显示myicon.ico,但字母A是透明的(而不是红色)。如果使用.bmp文件以(myicon.bmp)开头,文本将以正确的颜色显示(但边框是锯齿状的)。我玩过面具、前景和背景色,但都无济于事。

(我使用的是Windows7,Python 2.6,wxpython 2.8)

编辑:我缩短了解释时间,使代码更加独立。

简短回答:在我看来,这段wx代码中有一个错误。我要报告一下,看看结果如何。

长话短说:你可以随心所欲。设置图像中未使用的颜色。然后使用该颜色绘制,完成后,固定alpha值和这些像素的颜色以匹配您的期望:

import wx
from wx import ImageFromStream, BitmapFromImage, EmptyIcon
import cStringIO, zlib
# ================================ ICON ======================================
def getData():
    return zlib.decompress(
'xxdax01x97x03hxfcx89PNGrnx1anx00x00x00rIHDRx00x00x00x10
x00x00x00x10x08x06x00x00x00x1fxf3xffax00x00x00x04sBITx08
x08x08x08|x08dx88x00x00x03NIDAT8x8dmxd2MLx9bux00xc7xf1xefxf3
<xedxda><xa3@xcbx8ax0cpxac8x15x87x89/ x11xd1d&:5&#nxc9\xa2
xc6xc3bxe2xd1y0Y2xa3q^xccxb8x9axb9xf9rQcxc6x0esxa4xd1x91xe98
xc8x96xb98Hxc3x8bxc0xc6x00x91xd2xb2xa7}xdaxe7xa5xcfxd3xf6
xf9{0xa2x07xbfxf7_xf29xfc$x00xf1>xb2xd9xc7tI0$xc0xd5dx06xa5
x17qxf9Oxa5x0b$$x85KBxa2xecxcbxbcx1e}x81xdfx01$qx9a`>xcexc9`
xc7x91#xa1xcexa3;xedxdbgxb3sx19cxe1x9czxbe*Ax0fx80x80xf4A
xebxb0xfcPGxa2;x10x8aIxe5xd9x93x8bBxe6`lx88U)xf3-xc7xc3xbb_{
;rxefxe1Vcixa4xb0xbc:x17xb8xdczQxd3B5"Ax1fx00xa7"xe39x16xfb
xd6_xb1wux1f@xa9x15-kxe6xd4jxa2Dxbfxecx95x91xe5PGX_x18),.xcei
Wxdbxbfxd3:xb7{49x0exeemx1dkAG+Zxb4lxdfxc6o-xc3xeax9fKxbfx84
xe5xa6xfe&xa1>xa8xad)xecx96n}xc6`Exa8g7x95dxdbDxf2x82xdaxae
x06x08xd95x1exeejxa2xa1^F xa1x1b5xaexcfxe5xa8Dx14xeaxf4xf3
xdcox9esxb7x9933xe1Zxe9Utxe0xd8xe7x17?t4xecz7x99xd0hpx05x87
xf6ux927x0c6-x87xf6xd6x16x00xaax02xbeNxddxc2xd7x04x99xec:9K
xf9xf8xd37x07x8excbx00x99xca=xbdxbex00xbfxe4xb1wOx0cxbb*
x08x06x83x8cxfdxf8x03Exc3xa0xe2xba\x1axfbx99xee=qx8cxac
x83#7RtCx03x00x01x80rxd9xeaxa9z2x86xebx13x8bEpkx82:Uxe5x8f
x95x15xc6~x1a'=5xc9xb3xcfxefxa7qx87Jnxd3A4x04)x97xadx1ex00
x19xc0xb3-,xbbx82xe3xf9xb85xa8xf8x905Jxd4ix1axe9xa9I^:0xc4#
xbd}xb8Uxa8x>x96]xc1xb3-xb6x04^xd9Nx17Kx91gvxc6x03,elxeekx8b
x82x1cxe6xd1xc7xfbyxa0g/jxb4x1exd3x85xd5x8cE0"x91+xd9xe;xfd
xafxc0xb1xaex14rx03xbdxecrxf5xe6x06xc1x10xd4x85x83<5xf8$
xf1xc6zBx80x16x86_ofxf1xf0(x1ax06x9ec]xd9x12xb8xb63xea:xe6
xa1xd9x9axd2-xb7Uxf9bDxf0\ox82xaeDx1dx08Xxc9Zx8c^xcbP4xd6
x99xdfxb00xf3k3x08ex14@xfaxe7xeb}GOxbdxf5Xrxc7xf0BAS[xe3x1a
xb1Px08xc5x97xa9xf9x82x8aTxc5xf0\xaaxd5*xaaxb8kxa7xeflxbes
xfdxccxb1xd3[x02x80xe17x9ex98x8fFxa3jv3_;12xafxccJ*xb2x12x06
xc0xafx95iV+xbcxf7rRxc8rcDxa2kvxe0xccxdf;x19 x95J5x17nx85xef
xc3xe10fxa9`x98xf9;x1fxdaxb9xe9qkxe3x86nmxdcxd0xedxdcxf4xf8
xf2xf2xfcx07x85Bxdelx8exc7%]xd7/xa7Rxa9xe4x96xc04Mxc7qx9c
xb5x89x89x89N!xc4xd3Sxdf|4xcdxfftwxffx97_]xd3xf5Ixc0xf2}xdf
x02xf8x0bxc1.x9exd8Y.x85x85x00x00x00x00IENDxaeB`x822x86xba
xb3' )
def getBitmap():
    return BitmapFromImage(getImage())
def getImage():
    stream = cStringIO.StringIO(getData())
    return ImageFromStream(stream)
def getIcon():
    icon = EmptyIcon()
    icon.CopyFromBitmap(getBitmap())
    return icon
# ============================================================================
class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.number = 0
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.panel = wx.Panel(self)
        self.button = wx.Button(self.panel, label="Test")
        self.button.Bind(wx.EVT_BUTTON, self.OnButton)
        self.tbicon = wx.TaskBarIcon()
        self.tbicon.SetIcon(getIcon(), "Test")
        self.sizer = wx.BoxSizer()
        self.sizer.Add(self.button)
        self.panel.SetSizerAndFit(self.sizer)
        self.Show()
#   --------------------------------------------------------------------------
    def OnClose(self, e):
        self.tbicon.Destroy()
        self.Destroy()
        wx.Exit()
#   --------------------------------------------------------------------------
    def OnButton(self, e):
        # HERE WE GO!
        self.number += 1
        bitmap = getBitmap()
        # Find unused color
        image = bitmap.ConvertToImage()
        my_solid_color = wx.Color(*image.FindFirstUnusedColour(0, 0, 0)[1:])
        # Use the unused *unique* color to draw
        dc = wx.MemoryDC()
        dc.SetTextForeground(my_solid_color)
        dc.SelectObject(bitmap)
        dc.DrawText(str(self.number), 0, 0)
        dc.SelectObject(wx.NullBitmap)
        # Convert the bitmap to Image again 
        # and fix the alpha of pixels with that color 
        image = bitmap.ConvertToImage()
        for x in range(image.GetWidth()):
            for y in range(image.GetHeight()):
                p = wx.Colour(image.GetRed(x, y),
                              image.GetGreen(x, y),
                              image.GetBlue(x, y))
                if p == my_solid_color:
                    image.SetAlpha(x, y, 255)   # Clear the alpha
                    image.SetRGB(x, y, 0, 0, 0) # Set the color that we want
        # Convert back to Bitmap and save to Icon
        bitmap = image.ConvertToBitmap() 
        icon = wx.IconFromBitmap(bitmap)
        self.tbicon.SetIcon(icon, "Test")
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()

注意:A必须添加一些图标。您可以忽略代码的这一部分。

只是猜测,但也许可以将初始图标创建为"EmptyIcon",然后将bmp复制到其中。

import wx
class MyTaskBarIcon(wx.TaskBarIcon):
  ...
  icon = wx.EmptyIcon()
  bmp = wx.Bitmap("myicon.ico", wx.BITMAP_TYPE_ICO)
  bmp = WriteTextOnBitmap("A", bmp, color=wx.RED)    #this function is as in the link above
  icon.CopyFromBitmap(bmp)
  self.SetIcon(icon, APP_NAME_WITH_VERSION)
  ...

最新更新