我正在使用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()全局方法中添加其状态。
但对我来说,目前第二个屏幕根本没有渲染。另外请评论我的方法 - 有没有更好的方法来实现这一点 - 我应该注意什么,或者我的代码中有什么错误?
答案 0 :(得分:1)
一些解决方案。
我必须创建MyFrame
类来添加 sizer ,将 Panel 的大小调整为<em> Frame 大小。
我将DispatchState
ChangePanel
添加到MyFrame
以使其更加面向对象。现在 Panel 调用 Frame 函数ChangePanel
和 Frame 创建/销毁面板。
由于SecondPanel
和MainPanel
非常相似,我提出了一个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 ball2.png
admin0.png
admin1.png