【问题标题】:wxPython - drawing on transparent/alpha background (for custom widgets/panels)wxPython - 在透明/alpha 背景上绘图(用于自定义小部件/面板)
【发布时间】:2011-07-06 18:51:11
【问题描述】:

我正在 Ubuntu Linux 上学习 wxPython - 我想定义我自己的小部件,它基本上是一条线,我想在窗口周围移动。我在某个地方,但问题是我无法让“小部件”在透明背景上“绘图”;我能得到的最好的东西是这样的(黄线应该是一个具有透明背景的独立小部件 - 但那里的背景是黑色的噪音):

我想出的代码如下。我不希望整个窗口透明(wxpython - Python drawing on screen - Stack Overflow);我知道 wx.TRANSPARENT 仅用于文本,我应该尝试 wx.GCDC,我这样做了,但它不起作用(wx.PaintDC and SetBackgroundMode( wx.TRANSPARENT ) support - wxPython-users | Google Groups),显然,这在“wxGTK 不可能”( wxPython-users - transparent background for a panel widget)...

似乎唯一的方法是使用透明位图/图像,然后将其用作自定义小部件的背景,这是否正确?如果是这样,是否有可能直接在 wxPython 中生成此位图/图像(我的目标是一个独立的脚本,我不想让它依赖于外部 .png :) ) ?如果这是一种可能的方法,有人可以指点我一个最小的工作示例(因为我根本找不到这种用途的任何示例)..

提前感谢您的帮助,
干杯!

上面生成图片的代码:

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

import wx

class CustomLine(wx.Panel): #PyControl
    """
    A custom class for a line
    Modified from http://wiki.wxpython.org/CreatingCustomControls
    """
    def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition,
            size=wx.DefaultSize, style=wx.NO_BORDER, validator=wx.DefaultValidator,
            name="CustomLine"):
        """
        Default class constructor.

        @param parent: Parent window. Must not be None.
        @param id: CustomLine identifier. A value of -1 indicates a default value.
        @param label: Text to be displayed next to the checkbox.
        @param pos: CustomLine position. If the position (-1, -1) is specified
                    then a default position is chosen.
        @param size: CustomLine size. If the default size (-1, -1) is specified
                     then a default size is chosen.
        @param style: not used in this demo, CustomLine has only 2 state
        @param validator: Window validator.
        @param name: Window name.
        """
        #~ wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
        wx.Panel.__init__(self, parent, id, pos, size, style)

        # Bind the events related to our control: first of all, we use a
        # combination of wx.BufferedPaintDC and an empty handler for
        # wx.EVT_ERASE_BACKGROUND (see later) to reduce flicker
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
        self.lpen = wx.Pen('yellow', 2, wx.SOLID)   
        self.imagebkg = wx.EmptyImage( 10, 10 )
        #~ self.imagebkg.SetData((255,255,255))
        #~ self.imagebkg.SetAlphaData((1))

    def OnPaint(self, event):
        """ Handles the wx.EVT_PAINT event for CustomLine. """

        # If you want to reduce flicker, a good starting point is to
        # use wx.BufferedPaintDC.
        pdc = wx.BufferedPaintDC(self)
        dc = wx.GCDC(pdc) 

        # Is is advisable that you don't overcrowd the OnPaint event
        # (or any other event) with a lot of code, so let's do the
        # actual drawing in the Draw() method, passing the newly
        # initialized wx.BufferedPaintDC
        self.Draw(dc)

    def Draw(self, dc):
        """
        Actually performs the drawing operations, for the bitmap and
        for the text, positioning them centered vertically.
        """

        # Get the actual client size of ourselves
        width, height = self.GetClientSize()

        if not width or not height:
            # Nothing to do, we still don't have dimensions!
            return

        # Initialize the wx.BufferedPaintDC, assigning a background
        # colour and a foreground colour (to draw the text)
        #~ backColour = self.GetBackgroundColour()
        #~ backBrush = wx.Brush((1,1,1,150), wx.TRANSPARENT) # backColour
        #~ backBrush = wx.Brush((10,10,1,150)) # backColour
        dc.SetBackground(wx.TRANSPARENT_BRUSH) #() backBrush
        #~ dc.SetBackgroundMode(wx.TRANSPARENT)
        dc.Clear()

        dc.SetPen(self.lpen)
        dc.DrawLine(0, 0, 100, 100)

    def OnEraseBackground(self, event):
        """ Handles the wx.EVT_ERASE_BACKGROUND event for CustomLine. """

        # This is intentionally empty, because we are using the combination
        # of wx.BufferedPaintDC + an empty OnEraseBackground event to
        # reduce flicker
        pass

class MyTestFrame(wx.Frame):
    def __init__(self, parent, title):
        super(MyTestFrame, self).__init__(parent, title=title, 
            size=(250, 150))

        # the master panel of the frame - "Add a panel so it looks correct on all platforms"
        self.panel = wx.Panel(self, wx.ID_ANY)
            # self.panel.SetBackgroundColour(wx.Colour(124, 224, 124)) # to confirm the square is the panel

        self.mpanelA = wx.Panel(self.panel, -1, size=(200,50))
        self.mpanelA.SetBackgroundColour((200,100,200))
        self.mpanelB = wx.Panel(self.panel, -1, size=(50,200), pos=(50,30))
        self.mpanelB.SetBackgroundColour(wx.Colour(200,100,100,100))

        self.cline = CustomLine(self.panel, -1, size=(-1,200))

        self.Centre()
        self.Show()


if __name__ == '__main__':
    app = wx.App()
    MyTestFrame(None, 'Test')
    app.MainLoop()

【问题讨论】:

    标签: background wxpython widget transparency alpha


    【解决方案1】:

    也许你应该看看 GraphicsContext 而不是 dc (DrawingContext)。它对透明度有更好的支持,例如在面板上绘制透明矩形。

    【讨论】:

    • 太棒了,感谢@Lars - 很快就会检查并报告;干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 2018-09-14
    • 1970-01-01
    相关资源
    最近更新 更多