2012-02-03 150 views
3

我在寫一個需要匹配現有Windows應用程序外觀的wxPython應用程序。 我正試圖將靜態文本和按鈕控件放在具有漸變背景的面板上。以下是我找到的方式,但我不禁感到我失去了一些東西。我應該如何繪製靜態文本和自定義控件,並讓背景顯示?在wxPython中使用透明/半透明背景繪製控件有什麼選擇?

  1. 不知何故說服本地控制不繪製背景。這尤其適用。到wxStaticText
  2. 開啓全局系統選項 msw.window.no-clip-children讓背景顯示通過?
  3. 傳遞一個重繪功能,它的OnPaint處理

2時觸及了每個 控制的背景似乎是最簡單的,但我不知道它關閉的一個原因。是否有任何性能影響打開全球無剪輯兒童?有什麼辦法可以打開它只是爲了我想要的窗戶?

編輯:示例代碼和screnshots

很抱歉,如果這是開始看起來像一個問題的答案。我想知道是否有正確的方法來做到這一點。

Screenshot of three static text controls.

#!/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() 

回答

4

我就遇到了這個確切的問題前些天:如何顯示用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() 

一對夫婦的關鍵的東西:

  1. 窗口風格應該是wx.TRANSPARENT_WINDOW(所有的控制都是窗戶的wxWidgets)
  2. 使用GCDC代替正常的DC,因爲前者有更好的透明度支持

我注意到偶爾的問題,當父面板的背景不會失效時, TransparentText控件的ent被更新。這不一致,通常效果不錯。

+0

這個例子工作正常。我使用上面的示例進行了測試,並注意到只需將wx.TRANSPARENT_WINDOW添加到示例2即可正常工作。 所以總結一下:重寫paint事件併爲wx.TRANSPARENT_WINDOW設置樣式位。 wx.TRANSPARENT_WINDOW的文檔提供了一些不同的內容,但它像一個魅力。 – DanHorner 2012-03-25 05:00:19