在wxPython中移动/拖动后,透明面板不会更新其背景

时间:2014-04-03 21:18:27

标签: python image python-2.7 wxpython wxwidgets

我在Windows 8操作系统上使用python v2.7和wxPython v3.0。

下面提供的代码只是创建一个名为myPanel的透明面板,其中包含一个按钮。透明面板在mainPanel上创建,其中包含图像作为背景。 透明面板可以在框架中拖动。

问题:拖动透明面板后,我发现透明面板的背景不会自动更新。如何自动更新? How ever if I minimize the gui window and restore it again, the background of the transparent panel is updated automatically!我不明白这种影响的原因? 我尝试在Refresh()方法中使用Update()MouseUp(self, e)等,但遗憾的是没有任何帮助。 以下是该应用的屏幕截图。应用程序启动时,初始状态显示在下图中:

initial

拖动透明面板后,背景不会更新,如下图所示:

AfterDrag

在最小化应用程序窗口然后将其恢复后,您会注意到透明面板的背景会自动更新,如下图所示:

enter image description here

代码:可以从此处下载代码中使用的图像。 globe.jpg

import wx

class gui(wx.Frame):

    def __init__(self, parent, id, title):
        self.d = d = {}
        wx.Frame.__init__(self, None, id, title, size=(260,260), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
        statusbar = self.CreateStatusBar()
        self.mainPanel = mainPanel = wx.Panel(self)
        self.mainSizer = mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.myPanel = myPanel = wx.Panel(mainPanel, -1, style=wx.TRANSPARENT_WINDOW, size=(80,80))
        button1 = wx.Button(myPanel, -1, size=(30,30), pos=(10,10))
        button1.SetBackgroundColour('#fff111')
        mainSizer.Add(myPanel, 0, wx.ALL, 0)
        myPanel.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
        myPanel.Bind(wx.EVT_MOTION, self.MouseMove)
        myPanel.Bind(wx.EVT_LEFT_UP, self.MouseUp)
        image_file = 'globe.jpg'
        bmp1 = wx.Image(image_file, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        wx.StaticBitmap(mainPanel, -1, bmp1, (0, 0))
        mainPanel.Bind(wx.EVT_MOTION, self.MouseMove)
        mainPanel.Bind(wx.EVT_LEFT_UP, self.MouseUp)
        mainPanel.SetSizer(mainSizer)
        mainPanel.Layout()

    def MouseDown(self, e):   
        o = e.GetEventObject()
        sx,sy = self.mainPanel.ScreenToClient(o.GetPositionTuple())
        dx,dy = self.mainPanel.ScreenToClient(wx.GetMousePosition())
        o._x,o._y = (sx-dx, sy-dy)
        self.d['d'] = o

    def MouseMove(self, e):
        try:
            if 'd' in self.d:
                o = self.d['d']
                x, y = wx.GetMousePosition()
                o.SetPosition(wx.Point(x+o._x,y+o._y))
        except: pass

    def MouseUp(self, e):
        try:
            if 'd' in self.d: del self.d['d']
        except: pass

if __name__=='__main__':
    app = wx.App()
    frame = gui(parent=None, id=-1, title="Test")
    frame.Show()
    app.MainLoop()

感谢您的时间!

1 个答案:

答案 0 :(得分:1)

您可以创建自定义面板,然后根据它位于父框架顶部的位置在该面板上绘制地球的一部分。这种方法“伪造”了透明度。我在下面列举了一个例子。

import wx

class CustomPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent,-1,size=(80,80))
        self.Bind(wx.EVT_PAINT, self.OnPaint)


    def OnPaint(self, evt):
        parentw,parenth = self.GetParent().GetSize()

        image = wx.Image('globe.jpg', wx.BITMAP_TYPE_ANY)
        x,y = self.GetPosition()
        mywidth,myheight = self.GetSize()

        if x + mywidth >= parentw:
            mywidth = parentw - x
        if y + myheight >= parenth:
            myheight = parenth - y

        drawx = 0
        drawy = 0

        if x < 0:
            drawx = abs(x)
            x = 0
        if y < 0:
            drawy = abs(y)
            y = 0

        r = wx.Rect(x,y,mywidth,myheight)

        try:
            image = image.GetSubImage(r)
        except:
            # rectangle is out of parent
            print 'rect ',r ,' is out of parent frame'
            return 

        bitmap = image.ConvertToBitmap()

        pdc = wx.PaintDC(self)
        pdc.DrawBitmap(bitmap, drawx, drawy)

class gui(wx.Frame):

    def __init__(self, parent, id, title):
        self.d = d = {}
        wx.Frame.__init__(self, None, id, title, size=(260,260), style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.CLIP_CHILDREN)
        statusbar = self.CreateStatusBar()
        self.mainPanel = mainPanel = wx.Panel(self)
        self.mainSizer = mainSizer = wx.BoxSizer(wx.VERTICAL)
        #self.myPanel = myPanel = wx.Panel(mainPanel, -1, style=wx.TRANSPARENT_WINDOW, size=(80,80))
        self.myPanel = myPanel = CustomPanel(mainPanel)
        button1 = wx.Button(myPanel, -1, size=(30,30), pos=(10,10))
        button1.SetBackgroundColour('#fff111')

        button2 = wx.Button(myPanel, -1, size=(30,30), pos=(40,40))
        button2.SetBackgroundColour('#fff111')


        mainSizer.Add(myPanel, 0, wx.ALL, 0)
        myPanel.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
        myPanel.Bind(wx.EVT_MOTION, self.MouseMove)
        myPanel.Bind(wx.EVT_LEFT_UP, self.MouseUp)
        image_file = 'globe.jpg'
        bmp1 = wx.Image(image_file, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        wx.StaticBitmap(mainPanel, -1, bmp1, (0, 0))

        mainPanel.Bind(wx.EVT_MOTION, self.MouseMove)
        mainPanel.Bind(wx.EVT_LEFT_UP, self.MouseUp)
        mainPanel.SetSizer(mainSizer)
        mainPanel.Layout()

    def MouseDown(self, e):   
        o = e.GetEventObject()
        sx,sy = self.mainPanel.ScreenToClient(o.GetPositionTuple())
        dx,dy = self.mainPanel.ScreenToClient(wx.GetMousePosition())
        o._x,o._y = (sx-dx, sy-dy)
        self.d['d'] = o

    def MouseMove(self, e):
        try:
            if 'd' in self.d:
                o = self.d['d']
                x, y = wx.GetMousePosition()
                o.SetPosition(wx.Point(x+o._x,y+o._y))
                self.myPanel.Refresh()
        except: pass


    def MouseUp(self, e):
        try:
            if 'd' in self.d: del self.d['d']
        except: pass


if __name__=='__main__':
    app = wx.App()
    frame = gui(parent=None, id=-1, title="Test")
    frame.Show()
    app.MainLoop()