wxPython背景图像在框架上

时间:2012-12-09 17:10:31

标签: python graphics bitmap python-2.7 wxpython

MMGP回答但不会让我信任他;-)所以我至少会在这里提到他。 (我终于得到了他的信任...... 8 - )

双缓冲的

His linked discussion提供了一个基本代码,可以进行以下修改:

在第106行插入此开头(覆盖现有代码,直至到达此处显示的最后一行):

    # Here's the actual drawing code.
    cliWidth, cliHeight = self.GetClientSize()
    bmp=wx.Bitmap("Logo16x9.png")
    bmpWide = bmp.GetWidth()
    bmpHeight = bmp.GetHeight()
    img = bmp.ConvertToImage()
    scaleFactor = cliWidth/bmpWide
    bmp = wx.BitmapFromImage(img.Scale(int(bmpWide * scaleFactor), int(bmpHeight * scaleFactor)))
    bmpWide = bmp.GetWidth()
    bmpHeight = bmp.GetHeight()
    xPos = (cliWidth - (bmpWide))/2
    yPos = (cliHeight - (bmpHeight))/2
    # altered by me
    dc.DrawBitmap(bmp, xPos, yPos)


class TestFrame(wx.Frame):

我整天都在反对这一切。

我不熟悉使用wxPython模块绘制图形,当我需要在框架上绘制背景图像时,我发现this code如果图像是窗口的完整大小,则效果很好。

但是,我需要将公司徽标作为背景,并通过调整大小保持居中。在它的当前形式中,调整大小会导致一个小型国家大小的图形工件出现在屏幕上并显示任何调整大小事件。

徽标图像文件(在代码的第43行使用)是400x300(WxH)图像。

我正在寻找一种方法:动态调整我的图像以匹配wx.GetClientSize(), 或者一种避免/删除神器的方法。优选地,不涉及PIL或ImageMagick。应用程序必须仅在本地级别运行,并且与系统无关(Win,Lin和Mac),这些都不涉及网络活动或映射驱动器。

Python 2.7和wxPython 2.8

我正在使用的代码(带有我的修改注释)如下:

import wx

########################################################################
class MainPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent=parent)
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.frame = parent

        sizer = wx.BoxSizer(wx.VERTICAL)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)

        for num in range(4):
            label = "Button %s" % num
            btn = wx.Button(self, label=label)
            sizer.Add(btn, 0, wx.ALL, 5)
        hSizer.Add((1,1), 1, wx.EXPAND)
        hSizer.Add(sizer, 0, wx.TOP, 100)
        hSizer.Add((1,1), 0, wx.ALL, 75)
        self.SetSizer(hSizer)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

    #----------------------------------------------------------------------
    def OnEraseBackground(self, evt):
        """
        Add a picture to the background
        """
        # yanked from ColourDB.py
        dc = evt.GetDC()
        # Added by me
        cliWidth, cliHeight = self.GetClientSize()

        if not dc:
            dc = wx.ClientDC(self)
            rect = self.GetUpdateRegion().GetBox()
            dc.SetClippingRect(rect)
        dc.Clear()
        # use a 400x300 image
        bmp = wx.Bitmap("Logo4x3.png")
        # added by me
        xPos = (cliWidth - 400)/2
        yPos = (cliHeight - 300)/2
        # altered by me
        dc.DrawBitmap(bmp, xPos, yPos)
        #dc.DrawBitmap(bmp, 0, 0)

########################################################################
class MainFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, size=(600,450))
        panel = MainPanel(self)        
        self.Center()

########################################################################
class Main(wx.App):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, redirect=False, filename=None):
        """Constructor"""
        wx.App.__init__(self, redirect, filename)
        dlg = MainFrame()
        dlg.Show()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = Main()
    app.MainLoop()

更新:最新失败 - 修改后的第37至52行

if not dc:
    dc = wx.ClientDC(self)
    rect = self.GetUpdateRegion().GetBox()
    dc.SetClippingRect(rect)
dc.Clear()
# use a 400x300 image
bmp = wx.Bitmap("Logo4x3.png")
img = bmp.ConvertToImage()
scaleFactor = cliWidth/400
bmp = wx.BitmapFromImage(img.Scale(int(400*scaleFactor),int(300*scaleFactor)))
# added by me
#xPos = (cliWidth - 400)/2
#yPos = (cliHeight - 300)/2
# altered by me
#dc.DrawBitmap(bmp, xPos, yPos)
dc.DrawBitmap(bmp, 0, 0)

另一次尝试而另一次失败。输出与屏幕没有区别。此外,关于双缓冲的参考文档没有解决此问题,但确实遭受相同的结果。此代码修改原始行的第36到57行。

brsh = wx.Brush('#000000')


if not dc:
    dc = wx.ClientDC(self)
    rect = self.GetUpdateRegion().GetBox()
    dc.SetClippingRect(rect)
dc.SetBackground(brsh)
dc.SetDeviceOrigin(0,0)
dc.DestroyClippingRegion()
dc.Clear()
# use a 400x300 image
bmp = wx.Bitmap("Logo4x3.png")
img = bmp.ConvertToImage()
scaleFactor = cliWidth/400
bmp = wx.BitmapFromImage(img.Scale(int(400*scaleFactor),int(300*scaleFactor)))
# added by me
#xPos = (cliWidth - 400)/2
#yPos = (cliHeight - 300)/2
# altered by me
#dc.DrawBitmap(bmp, xPos, yPos)
dc.DrawBitmap(bmp, 0, 0)

1 个答案:

答案 0 :(得分:5)

从我建议使用双缓冲绘图的评论,但我没有在编辑的帖子中看到。此外,在使用self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)时,我遇到了几个绘图问题。但是这条线可能对我以外的其他系统有所帮助,所以我想保留它。因此,为了处理这种情况,这里有一个使用双缓冲绘图的更新代码,在这里工作正常:

import wx

class MainPanel(wx.Panel):
    def __init__(self, parent, bg_img='Logo4x3.png'):
        wx.Panel.__init__(self, parent=parent)
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.bg = wx.Bitmap(bg_img)
        self._width, self._height = self.bg.GetSize()

        sizer = wx.BoxSizer(wx.VERTICAL)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)

        for num in range(4):
            btn = wx.Button(self, label="Button %s" % num)
            sizer.Add(btn, 0, wx.ALL, 5)
        hSizer.Add((1,1), 1, wx.EXPAND)
        hSizer.Add(sizer, 0, wx.TOP, 100)
        hSizer.Add((1,1), 0, wx.ALL, 75)
        self.SetSizer(hSizer)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

    def OnSize(self, size):
        self.Layout()
        self.Refresh()

    def OnEraseBackground(self, evt):
        pass

    def OnPaint(self, evt):
        dc = wx.BufferedPaintDC(self)
        self.Draw(dc)

    def Draw(self, dc):
        cliWidth, cliHeight = self.GetClientSize()
        if not cliWidth or not cliHeight:
            return
        dc.Clear()
        xPos = (cliWidth - self._width)/2
        yPos = (cliHeight - self._height)/2
        dc.DrawBitmap(self.bg, xPos, yPos)

app = wx.App()
frame = wx.Frame(None, size=(400,300))
panel = MainPanel(frame)
frame.Show()
app.MainLoop()

方法OnEraseBackground故意为空。