wxPython帧上的背景图像

wxPython帧上的背景图像,python,graphics,bitmap,python-2.7,wxpython,Python,Graphics,Bitmap,Python 2.7,Wxpython,MMGP回答了,但不让我相信他是对的;-)所以我至少会在这里提到他。 (我终于相信了他……8-) 在双缓冲上,提供了一个基本代码,该代码进行了以下修改: 从第106行开始插入(覆盖现有代码,直到到达此处显示的最后一行): 我一整天都在和这件事做斗争 我对使用wxPython模块绘制图形还不熟悉,当我需要在一个框架上绘制背景图像时,我发现如果图像是窗口的全尺寸,那么这个框架可以很好地工作 但是,我需要放置一个公司徽标作为背景,并通过调整大小使其保持居中。在它的当前形式中,调整大小会导致一个小国家大

MMGP回答了,但不让我相信他是对的;-)所以我至少会在这里提到他。 (我终于相信了他……8-)

在双缓冲上,提供了一个基本代码,该代码进行了以下修改:

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

我一整天都在和这件事做斗争

我对使用wxPython模块绘制图形还不熟悉,当我需要在一个框架上绘制背景图像时,我发现如果图像是窗口的全尺寸,那么这个框架可以很好地工作

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

徽标图像文件(用于代码第43行)是400x300(WxH)图像

我正在寻找一种方法:动态调整图像大小以匹配wx.GetClientSize(), 或者一种避免/移除工件的方法。最好不涉及PIL或ImageMagick。应用程序必须仅在本地级别运行,且不受系统影响(Win、Lin和Mac),所有这些都不涉及网络活动或映射驱动器

Python2.7和Wxpython2.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)

从我的评论中,我建议使用双缓冲绘图,但我在编辑的帖子中没有看到。另外,当使用
self.SetBackgroundStyle(wx.BG\u STYLE\u 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
故意为空。

闪烁是您所指的工件吗?这是解决了双缓冲绘图,特别是看不到闪烁。重新绘制后,原始图像的75%副本保留下来。结果看起来像两个正方形(彩色的)重叠了25%。(一般来说,标志是方形的)更好的解释。原始图像永远不会擦除。新图像(调整大小后)已正确绘制,但现在两个图像都位于曲面上。奇怪的是,新图像在旧图像的下方(较低的z索引)绘制。在我看来,前面的链接仍然适用。你检查过了吗?@mmgp刚刚发布了相关信息……双缓冲上的链接穿过同一个字段,但没有解决失败的擦除步骤。另外(上面没有注意到这一点)已经尝试将其绑定到EXT_SIZE和EVT_PAINT,结果没有任何差异。感谢额外的代码…我正要尝试从您链接的原始示例中去掉所有的废话。这将使生活更轻松。现在开始基于此重建我的想法……这在Linux上也有效吗?我现在不能在那里测试它。我在那里尝试的一些WM中失败得很厉害,我会回到这里。请参阅更新的代码,以防前面的代码在某个地方失败。
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()