wxPython开发总结---Frame,Panel以及一种项目架构

前一段时间用Python开发了一个教育类的PC桌面应用,边学边开发,现在陆续的将开发过程中学到的一些东西分享记录下来,项目使用了wxPython框架。



wxPython的官网: https://www.wxpython.org/

wxPython各种控件用法官方手册 : http://xoomer.virgilio.it/infinity77/wxPython/widgets.html


wx库不是Python自带的库文件,需要首先在官网下载并安装,windows可以在官网下载exe安装文件,Ubuntu和Mac可以使用pip install进行安装,也可以使用源码安装方式安装。

安装成功之后,使用import wx 来测试安装成功与否,在进行wxPython编程中,也需要使用import wx 首先导入wxPython的库引用。

下面是第一个用wxPython构建的界面窗口:

【效果】


【代码实现】

#coding=utf-8
"""
程序的主入口
"""
import wx


class FirseFrame(wx.Frame):
    def __init__(self, parent=None, id=-1, title='', pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.DEFAULT_FRAME_STYLE):
        """
        wx.Frame() 构造函数参数说明 :
        wx.Frame.__init__(self, Window parent, int id=-1, String title=EmptyString,
            Point pos=DefaultPosition, Size size=DefaultSize,
           long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> Frame
        """
        wx.Frame.__init__(self, parent, id, title, pos, size, style)

        self.InitUI()
        pass
    def InitUI(self):
        self.SetBackgroundColour('#ffffff')
        """
        wx.StaticText()构造函数参数说明 :
        __init__(self, Window parent, int id=-1, String label=EmptyString,
            Point pos=DefaultPosition, Size size=DefaultSize,
            long style=0, String name=StaticTextNameStr) -> StaticText
        """
        content = wx.StaticText(self, -1, u'这是第一个窗口', pos=(20, 20))
        content.SetForegroundColour('#000000')
        pass

class MainApp(wx.App):
    def OnInit(self):
        self.frame = FirseFrame(id=-1, title=u'第一个窗口', pos=(10, 10), size=(230, 230))
        self.frame.Show()
        return True

def main():
    app = MainApp()
    app.MainLoop()

if __name__ == "__main__":
    main()


【说明】

if __name__ == "__main__":
    main()
上面的代码是Python程序的主入口,在一个项目中有且只有一个,一个Python程序开始运行的时候,会找到这个入口,并从此开始运行。

class MainApp(wx.App):
    def OnInit(self):
        self.frame = FirseFrame(id=-1, title=u'第一个窗口', pos=(10, 10), size=(230, 230))
        self.frame.Show()
        return True

wx.App是wxPython中一个App对象,在一个wxPython中有且只有一个,MainApp类继承了wx.App类MainApp类被实例化之后,调用wx.App对象的MainLoop()方法便开始了一个wxPython进程。


关于编码错误的问题,上面程序中,汉字字符串前面加了一个u,表示该段字符串的编码/解码方式是unicode的方式,如果项目运行Unicode编码错误,可以在程序开始的地方加上下面一段代码:

import sys

reload(sys)
sys.setdefaultencoding('utf-8')

(1)wx.Frame

Frame可以看做是wxPython提供的控件绘制的窗口,我们可以将控件绘制在Frame上,便于管理。

在wxPython的源码中可以看到wxFrame的构造函数为:

"""
wx.Frame() 构造函数参数说明 :
__init__(self, Window parent, int id=-1, String title=EmptyString,
    Point pos=DefaultPosition, Size size=DefaultSize,
   long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> Frame
"""
【说明】

pos是Frame在屏幕上显示的位置, size为Frame窗口初始化绘制的大小

style是Frame显示的属性,常用的style样式说明:

style=wx.CAPTION : 在Frame上增加一个标题栏 :



style=wx.CLOSE_BOX : 在Frame上显示关闭框:

style=wx.MAXIMIZE_BOX :   在Frame上显示最大化框

style=wx.MINIMIZE_BOX :  在Frame上显示最小化框

style=wx.RESIZE_BORDER : 给Frame添加一个用户可以自己改变Frame大小的边框

style=wx.DEFAULT_FRAME_STYLE : 默认的Frame样式:


可以看到默认样式包含了所有的常见样式(包括,标题,icon,最小化,最大化,可拖拽大小边框,关闭),那么要是我们想在默认样式的基础上出去某个样式,可以:

style = wx.DEFAULT_FRAME_STYLE^(wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX|wx.CLOSE_BOX)
上面的样式在默认样式的基础上,去除了 拖拽改变Frame大小属性,去除了最大化,去除了最小化,去除了关闭。

效果如下:


当然要是只去除一个样式,e.g. 去除最大化:

style = wx.DEFAULT_FRAME_STYLE^wx.MAXIMIZE_BOX
self.frame = FirseFrame(id=-1, title=u'第一个窗口', pos=(10, 10), size=(230, 230), style=style)
效果:



pos是一个Frame显示在屏幕上的位置坐标,size是Frame初始化的大小,那么要是我们希望我们的Frame在初始化之后显示在屏幕的中间,可以首先获得屏幕的大小,然后动态规定pos的值:

class MainApp(wx.App):
    def OnInit(self):
        style = wx.DEFAULT_FRAME_STYLE^wx.MAXIMIZE_BOX
        # wx.DisplaySize()获得一个元组, e.g. (1440, 780) 表示当前设备屏幕的长宽
         windowSize = wx.DisplaySize()
        newPos = (windowSize[0] / 2, windowSize[1] / 2)
        self.frame = FirseFrame(id=-1, title=u'第一个窗口', pos=newPos, size=(230, 230), style=style)
        self.frame.Show()
        return True
上面的代码通过wx.DisplaySize()获得了设备屏幕的大小,动态制定了Frame显示的坐标,使得Frame左上角位于屏幕的中心位置,这是一种方法,其实wxPython提供了一种自带的接口:

只修改wxFrame类:

class FirseFrame(wx.Frame):
    def __init__(self, parent=None, id=-1, title='', pos=wx.DefaultSize, size=wx.DefaultSize, style= wx.DEFAULT_FRAME_STYLE):

        wx.Frame.__init__(self, parent, id, title, pos, size, style)

        self.InitUI()
        pass
    def InitUI(self):
        self.SetBackgroundColour('#ffffff')
        """
        wx.StaticText()构造函数参数说明 :
        __init__(self, Window parent, int id=-1, String label=EmptyString,
            Point pos=DefaultPosition, Size size=DefaultSize,
            long style=0, String name=StaticTextNameStr) -> StaticText
        """
        content = wx.StaticText(self, -1, u'这是第一个窗口', pos=(20, 20))
        content.SetForegroundColour('#000000')

        self.Center()
        pass
在FirseFrame(wx.Frame)的InitUI()函数的最后调用了 self.Center() 函数,告诉系统将该Frame显示在屏幕的中间,系统会将Frame的中心放在设备屏幕的中心位置,

同样的,要是想让Frame在初始化之后,最大化,一种方法就是将Frame的size设置为wx.DisplaySize(),和self.Center()相同,可以通过调用self.Maximize(True)来实现:

self.Maximize(True)

(2)wx.Panel

Panel可以看做是一个碎片化的Frame,当有一部分的控件需要同时处理,比如同时隐藏,同时显示的时候,可以将这些控件的parent Window写成同一个Panel,这样方便于整体的操作。

"""
__init__(self, Window parent, int id=-1, Point pos=DefaultPosition, 
    Size size=DefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER, 
    String name=PanelNameStr) -> Panel
"""

(3)一种wxPython项目架构

当我们有多个Frame界面需要来回的跳转,而Frame的显示是在MainApp(wx.App)类中实现的,那么就需要在MainApp(wx.App)这个类中实现一个Frame跳转的接口,通过这个接口来完成多Frame的跳转。


【说明】

FrameManager中,维护了一个字典,key=type,value=Frame,首次显示Frame的时候,创建该Frame,并将其缓存在字典中,再次显示该Frame的时候,直接从字典中获取得到gaiFrame,并通过Frame中自定义的方法UpdateDataAndUI(self, newData)接口,更新Frame的数据和显示状态。


源码和更多说明请查看:

相关内容推荐