1

我正在使用具有 4 页(或更多页)的 wxPython 编写 GUI 流。我接触的方法是创建 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() 全局方法中。

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

4

1 回答 1

1

一些解决方案。

我必须创建MyFrame类来添加将Panel调整为Frame大小的sizer

我添加DispatchStateChangePanel使其MyFrame更加面向对象。现在Panel调用Frame函数ChangePanelFrame创建/销毁面板。

因为SecondPanelMainPanel非常相似,我做了一MyPanel门课 - 减少我的错误的工作:) - 请参阅DRY规则:不要重复自己

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

我使用 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()

球1.png 球球1.png2.png球2.png

admin0.png admin0.png

admin1.png admin1.png

于 2013-11-11T19:00:02.170 回答