wxpython:动态更改背景/前景图像

时间:2013-11-11 09:23:22

标签: wxpython

我正在使用wxPython编写GUI流程,该流程有4页(或更多)。他们接近的方式是创建4个(或更多)类,每个类定义自己的静态(背景)和动态图像/内容。在我的应用程序中,我将以编程方式创建所需的实例类并捕获该页面上的事件。根据触发的事件,注册的处理程序将销毁当前类并切换到其他类(页面)。所以我的代码实际上创建了X类,每个类都有自己的方法来设置背景/前景内容/图像:

def OnEraseBackground(self, evt):
    dc = evt.GetDC()

    if not dc:
        dc = wx.ClientDC(self)
        rect = self.GetUpdateRegion().GetBox()
        dc.SetClippingRect(rect)
    dc.Clear()
    bmp = wx.Bitmap(self.image)
    dc.DrawBitmap(bmp, 0, 0)

def buttonClick(self, evt):
    parent = self.frame
    self.Destroy()
    DispatchState(parent, "admin1.png", 1)

问题是第二页在屏幕上根本没有出现。

以下是我的完整代码。注意我已经创建了2个类(MainPanel,SecondPanel),它在我的应用程序框架中的面板上创建了一个屏幕。然后它等待一个事件。一旦我得到了想要的事件,我就删除当前的类并创建一个新类的实例:

import wx

########################################################################
class SecondPanel(wx.Panel):
    def __init__(self,parent, image, state):
        wx.Panel.__init__(self, parent=parent)
    self.state = state
    self.image = image
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.frame = parent
        sizer = wx.BoxSizer(wx.VERTICAL)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
    panel=wx.Panel(self, -1)

    self.buttonOne=wx.Image("image1.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
    self.button=wx.BitmapButton(self, -1, self.buttonOne, pos=(100,50))
    self.button.Bind(wx.EVT_LEFT_DCLICK, self.buttonClick)
        sizer.Add(self.button, 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 buttonClick(self, evt):
    parent = self.frame
    self.Destroy()
    DispatchState(parent, "admin0.png", 0)

    def OnEraseBackground(self, evt):
    dc = evt.GetDC()

    if not dc:
        dc = wx.ClientDC(self)
        rect = self.GetUpdateRegion().GetBox()
        dc.SetClippingRect(rect)
    dc.Clear()
    bmp = wx.Bitmap(self.image)
    dc.DrawBitmap(bmp, 0, 0)

class MainPanel(wx.Panel):
    def __init__(self,parent, image, state):
        wx.Panel.__init__(self, parent=parent)
    self.state = state
    self.image = image
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        self.frame = parent
        sizer = wx.BoxSizer(wx.VERTICAL)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
    panel=wx.Panel(self, -1)
    self.buttonOne=wx.Image("image0.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
    self.button=wx.BitmapButton(self, -1, self.buttonOne, pos=(100,50))
    self.button.Bind(wx.EVT_LEFT_DCLICK, self.buttonClick)
        sizer.Add(self.button, 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 buttonClick(self, evt):
    parent = self.frame
    self.Destroy()
    DispatchState(parent, "admin1.png", 1)

    def OnEraseBackground(self, evt):
    dc = evt.GetDC()

    if not dc:
        dc = wx.ClientDC(self)
        rect = self.GetUpdateRegion().GetBox()
        dc.SetClippingRect(rect)
    dc.Clear()
    bmp = wx.Bitmap(self.image)
    dc.DrawBitmap(bmp, 0, 0)


 class Main(wx.App):
    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename)
        self.frame = wx.Frame(None, size=(800, 480))
        self.state = 0
        self.image = 'admin0.png'

def DispatchState(frame, image, state):
        if state == 0 :
            print image
            print state
            MainPanel(frame, image, state)
        if state == 1 :
            print image
            print state
            SecondPanel(frame, image, state)
        frame.Show()


if __name__ == "__main__":
    app = Main()
    DispatchState(app.frame,app.image, app.state)
    app.MainLoop()

我选择这种方法的原因是我可以轻松地从一种状态切换到另一种状态,这样我就可以切换到任何屏幕/页面。如果明天我们需要动态添加/删除更多页面 - 可以轻松完成。我需要创建页面(类)并在DispatchState()全局方法中添加其状态。

但对我来说,目前第二个屏幕根本没有渲染。另外请评论我的方法 - 有没有更好的方法来实现这一点 - 我应该注意什么,或者我的代码中有什么错误?

1 个答案:

答案 0 :(得分:1)

一些解决方案。

我必须创建MyFrame类来添加 sizer ,将 Panel 的大小调整为<​​em> Frame 大小。

我将DispatchState ChangePanel添加到MyFrame以使其更加面向对象。现在 Panel 调用 Frame 函数ChangePanel Frame 创建/销毁面板。

由于SecondPanelMainPanel非常相似,我提出了一个MyPanel课程 - 减少了错误的工作量:) - 请参阅 DRY 规则: Don't Repeat Yourself

我附上我的位图,以便其他用户也可以运行此代码

我使用ball1.png,ball2.png到位image0.bmp,image1.bmp

import wx

#######################################################################

class MyPanel(wx.Panel):

    def __init__(self, parent, state, button_image, background_image):
        wx.Panel.__init__(self, parent=parent)

        print "(debug) MyPanel.__init__: state:", state

        self.parent = parent
        self.state  = state

        self.button_image = button_image
        self.background_image = background_image


        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)

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

        #self.buttonOne=wx.Image("image1.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
        self.buttonImage = wx.Image(button_image, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
        self.button = wx.BitmapButton(self, -1, self.buttonImage, pos=(100,50))

        self.button.Bind(wx.EVT_LEFT_DCLICK, self.buttonClick)

        self.backgroundImage = wx.Bitmap(self.background_image)

        vsizer.Add(self.button, 0, wx.ALL, 5)

        hSizer.Add((1,1), 1, wx.EXPAND)
        hSizer.Add(vsizer, 0, wx.TOP, 100)
        hSizer.Add((1,1), 0, wx.ALL, 75)

        self.SetSizer(hSizer)

        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

    def buttonClick(self, evt):
        print "(debug) MyPanel.buttonClick"
        self.parent.ChangePanel()

    def OnEraseBackground(self, evt):
        dc = evt.GetDC()

        if not dc:
            dc = wx.ClientDC(self)
            rect = self.GetUpdateRegion().GetBox()
            dc.SetClippingRect(rect)
        dc.Clear()
        dc.DrawBitmap(self.backgroundImage, 0, 0)

#######################################################################

class MyFrame(wx.Frame):

    def __init__(self, size=(800,480)):
        wx.Frame.__init__(self, None, size=size)

        self.state = None
        self.panel = None

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)

        self.Show() # Show is used to show/hide window not to update content

        self.ChangePanel()

    #--------------------------

    def ChangePanel(self):

        print "(debug) MyFrame.ChangePanel: state:", self.state

        if self.state is None or self.state == 1:
            # change state
            self.state = 0 

            # destroy old panel
            if self.panel:
                self.panel.Destroy()

            # create new panel
            self.panel = MyPanel(self, self.state, "ball1.png", "admin0.png")

            # add to sizer
            self.sizer.Add(self.panel, 1, wx.EXPAND)
        elif self.state == 0 :
            # change state
            self.state = 1 

            # destroy old panel
            if self.panel:
                self.panel.Destroy()

            # create new panel
            self.panel = MyPanel(self, self.state, "ball2.png", "admin1.png")

            # add to sizer
            self.sizer.Add(self.panel, 1, wx.EXPAND)
        else:
            print "unkown state:", self.state

        self.Layout() # refresh window content

#######################################################################

class Application(wx.App):

    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename)   
        self.frame = MyFrame((800, 480))

    def run(self):
        self.MainLoop()

#######################################################################

if __name__ == "__main__":
    Application().run()

ball1.png ball1.png ball2.png ball2.png

admin0.png admin0.png

admin1.png admin1.png