在wxPython中绘制透明/半透明背景控件的选项有哪些?
我正在写一个wxPython应用程序,想让它的外观和一个现有的Windows应用程序一致。现在我想在一个面板上放置静态文本和按钮控件,并且希望背景是渐变的。我找到了一些方法,但总觉得还缺少什么。请问我该如何绘制静态文本和自定义控件,让背景透出来呢?
- 想办法让原生控件不绘制背景,特别是wxStaticText这个控件。
- 开启一个全局系统选项
msw.window.no-clip-children
,让背景透出来? - 传入一个重绘函数,在每个控件的onPaint处理器中修整背景。
第二种方法看起来最简单,但我在想这样做是否有原因被关闭。开启no-clip-children这个选项会对性能有影响吗?有没有办法只对我想要的窗口开启这个选项?
编辑:示例代码和截图
抱歉如果这看起来像是在回答问题。我想知道有没有正确的方法来做到这一点。
#!/usr/bin/python
import wx
class GradientPanel(wx.Panel):
def __init__(self,*args,**kwargs):
wx.Panel.__init__(self,*args,**kwargs)
self.Bind(wx.EVT_PAINT,lambda e: self.paintBackground())
self.Bind(wx.EVT_ERASE_BACKGROUND,lambda e: None)
self.t=wx.StaticText(self,pos=(30,20),label="wxStaticText. Looks bad on MSW")
self.t2=MyStaticText(self,pos=(30,50), size=(300,25), label="MyStaticText. Needs ClipChildren turned off")
self.t3=MyStaticTextWithCustomBackground(self,pos=(30,80),size=(300,25), label="This Control touches up its own background",paintBackgroundToDC=self.paintBackgroundToDC)
def paintBackground(self):
dc=wx.PaintDC(self)
self.paintBackgroundToDC(self,dc)
def paintBackgroundToDC(self,ofWindow,dc=None):
r=self.GetScreenRect()
r.SetTopLeft(ofWindow.ScreenToClient(r.GetTopLeft()))
dc.GradientFillLinear(r,wx.Colour(240,240,240),wx.Colour(128,128,255),wx.SOUTH)
class MyStaticText(wx.Window):
def __init__(self,parent,label,**kwargs):
wx.Window.__init__(self,parent,**kwargs)
self.label=label
self.Bind(wx.EVT_PAINT,lambda e: self.repaint())
self.Bind(wx.EVT_ERASE_BACKGROUND,lambda e: None)
def repaint(self):
self.repaintToDC(wx.PaintDC(self))
def repaintToDC(self,dc):
dc.DrawText(self.label,0,0)
class MyStaticTextWithCustomBackground(MyStaticText):
def __init__(self,parent,label,paintBackgroundToDC=None,**kwargs):
self.paintBackgroundToDC=paintBackgroundToDC
MyStaticText.__init__(self,parent,label,**kwargs)
def repaint(self):
dc=wx.PaintDC(self)
if self.paintBackgroundToDC:
self.paintBackgroundToDC(self,dc)
MyStaticText.repaintToDC(self,dc)
if __name__ == "__main__":
#wx.SystemOptions.SetOptionInt('msw.window.no-clip-children',1)
app=wx.PySimpleApp()
frame=wx.Frame(None,title="Transparent Controls")
panel=GradientPanel(frame)
frame.Show()
app.MainLoop()
1 个回答
5
我前几天遇到了一个问题:如何在wxPython中显示带透明背景的静态文本。于是我想出了以下方法:
class TransparentText(wx.StaticText):
def __init__(self, parent, id=wx.ID_ANY, label='', pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.TRANSPARENT_WINDOW, name='transparenttext'):
wx.StaticText.__init__(self, parent, id, label, pos, size, style, name)
self.Bind(wx.EVT_PAINT, self.on_paint)
self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
self.Bind(wx.EVT_SIZE, self.on_size)
def on_paint(self, event):
bdc = wx.PaintDC(self)
dc = wx.GCDC(bdc)
font_face = self.GetFont()
font_color = self.GetForegroundColour()
dc.SetFont(font_face)
dc.SetTextForeground(font_color)
dc.DrawText(self.GetLabel(), 0, 0)
def on_size(self, event):
self.Refresh()
event.Skip()
这里有几个关键点:
- 窗口的样式应该设置为wx.TRANSPARENT_WINDOW(在wxwidgets中,所有控件都是窗口)
- 要使用GCDC,而不是普通的DC,因为GCDC对透明度的支持要好得多
我注意到有时候,父面板的背景在更新TransparentText控件的内容时不会被刷新。这种情况并不总是发生,通常情况下效果还是不错的。