在本节中,我们将创建一些应用框架。 我们的脚本将制定出接口,但不会实现该功能。 目的是展示如何在 wxPython 中完成几个众所周知的 GUI 界面。
文件管理器
文件监视器是文件管理器的骨架。 它复制了 Krusader 的监视,Krusader 是 Unix 系统上可用的文件管理器。 如果我们双击拆分器小部件,它将把文件监视器分成宽度相同的两个部分。 如果我们调整主窗口的大小,也会发生同样的情况。
file_hunter.py
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""ZetCode wxPython tutorialThis program creates a skeletonof a file manager UI.author: Jan Bodnarwebsite: zetcode.comlast edited: May 2018"""import wximport osimport timeID_BUTTON=100ID_EXIT=200ID_SPLITTER=300class MyListCtrl(wx.ListCtrl):def __init__(self, parent):wx.ListCtrl.__init__(self, parent, style=wx.LC_REPORT)images = ['images/empty.png', 'images/folder.png', 'images/source-py.png','images/image.png', 'images/pdf.png', 'images/up16.png']self.InsertColumn(0, 'Name')self.InsertColumn(1, 'Ext')self.InsertColumn(2, 'Size', wx.LIST_FORMAT_RIGHT)self.InsertColumn(3, 'Modified')self.SetColumnWidth(0, 220)self.SetColumnWidth(1, 70)self.SetColumnWidth(2, 100)self.SetColumnWidth(3, 420)self.il = wx.ImageList(16, 16)for i in images:self.il.Add(wx.Bitmap(i))self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)j = 1self.InsertItem(0, '..')self.SetItemImage(0, 5)files = os.listdir('.')for i in files:(name, ext) = os.path.splitext(i)ex = ext[1:]size = os.path.getsize(i)sec = os.path.getmtime(i)self.InsertItem(j, name)self.SetItem(j, 1, ex)self.SetItem(j, 2, str(size) + ' B')self.SetItem(j, 3, time.strftime('%Y-%m-%d %H:%M', time.localtime(sec)))if os.path.isdir(i):self.SetItemImage(j, 1)elif ex == 'py':self.SetItemImage(j, 2)elif ex == 'jpg':self.SetItemImage(j, 3)elif ex == 'pdf':self.SetItemImage(j, 4)else:self.SetItemImage(j, 0)if (j % 2) == 0:self.SetItemBackgroundColour(j, '#e6f1f5')j = j + 1class Example(wx.Frame):def __init__(self, *args, **kw):super(Example, self).__init__(*args, **kw)self.InitUI()def InitUI(self):self.splitter = wx.SplitterWindow(self, ID_SPLITTER, style=wx.SP_BORDER)self.splitter.SetMinimumPaneSize(50)p1 = MyListCtrl(self.splitter)p2 = MyListCtrl(self.splitter)self.splitter.SplitVertically(p1, p2)self.Bind(wx.EVT_SIZE, self.OnSize)self.Bind(wx.EVT_SPLITTER_DCLICK, self.OnDoubleClick, id=ID_SPLITTER)filemenu= wx.Menu()filemenu.Append(ID_EXIT, "E&xit"," Terminate the program")editmenu = wx.Menu()netmenu = wx.Menu()showmenu = wx.Menu()configmenu = wx.Menu()helpmenu = wx.Menu()menuBar = wx.MenuBar()menuBar.Append(filemenu, "&File")menuBar.Append(editmenu, "&Edit")menuBar.Append(netmenu, "&Net")menuBar.Append(showmenu, "&Show")menuBar.Append(configmenu, "&Config")menuBar.Append(helpmenu, "&Help")self.SetMenuBar(menuBar)self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT)tb = self.CreateToolBar( wx.TB_HORIZONTAL | wx.NO_BORDER |wx.TB_FLAT)tb.AddTool(10, 'Previous', wx.Bitmap('images/previous.png'), shortHelp='Previous')tb.AddTool(20, 'Up', wx.Bitmap('images/up.png'), shortHelp='Up one directory')tb.AddTool(30, 'Home', wx.Bitmap('images/home.png'), shortHelp='Home')tb.AddTool(40, 'Refresh', wx.Bitmap('images/refresh.png'), shortHelp='Refresh')tb.AddSeparator()tb.AddTool(50, 'Edit text', wx.Bitmap('images/textedit.png'), shortHelp='Edit text')tb.AddTool(60, 'Terminal', wx.Bitmap('images/terminal.png'), shortHelp='Terminal')tb.AddSeparator()tb.AddTool(70, 'Help', wx.Bitmap('images/help.png'), shortHelp='Show help')tb.Realize()self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)button1 = wx.Button(self, ID_BUTTON + 1, "F3 View")button2 = wx.Button(self, ID_BUTTON + 2, "F4 Edit")button3 = wx.Button(self, ID_BUTTON + 3, "F5 Copy")button4 = wx.Button(self, ID_BUTTON + 4, "F6 Move")button5 = wx.Button(self, ID_BUTTON + 5, "F7 Mkdir")button6 = wx.Button(self, ID_BUTTON + 6, "F8 Delete")button7 = wx.Button(self, ID_BUTTON + 7, "F9 Rename")button8 = wx.Button(self, ID_EXIT, "F10 Quit")self.sizer2.Add(button1, 1, wx.EXPAND)self.sizer2.Add(button2, 1, wx.EXPAND)self.sizer2.Add(button3, 1, wx.EXPAND)self.sizer2.Add(button4, 1, wx.EXPAND)self.sizer2.Add(button5, 1, wx.EXPAND)self.sizer2.Add(button6, 1, wx.EXPAND)self.sizer2.Add(button7, 1, wx.EXPAND)self.sizer2.Add(button8, 1, wx.EXPAND)self.Bind(wx.EVT_BUTTON, self.OnExit, id=ID_EXIT)self.sizer = wx.BoxSizer(wx.VERTICAL)self.sizer.Add(self.splitter,1,wx.EXPAND)self.sizer.Add(self.sizer2,0,wx.EXPAND)self.SetSizer(self.sizer)# size = wx.DisplaySize()# self.SetSize(size)sb = self.CreateStatusBar()sb.SetStatusText(os.getcwd())self.SetTitle("File Hunter")self.Center()def OnExit(self, e):self.Close(True)def OnSize(self, e):size = self.GetSize()self.splitter.SetSashPosition(size.x / 2)e.Skip()def OnDoubleClick(self, e):size = self.GetSize()self.splitter.SetSashPosition(size.x / 2)def main():app = wx.App()ex = Example(None)ex.Show()app.MainLoop()if __name__ == '__main__':main()
该示例创建一个两面板文件管理器的 UI。
class MyListCtrl(wx.ListCtrl):def __init__(self, parent):wx.ListCtrl.__init__(self, parent, style=wx.LC_REPORT)
应用的主要区域被wx.ListCtrl小部件占据。
self.il = wx.ImageList(16, 16)for i in images:self.il.Add(wx.Bitmap(i))self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
列表控件包含一个列表图像,用于指示文件类型。
files = os.listdir('.')for i in files:(name, ext) = os.path.splitext(i)ex = ext[1:]size = os.path.getsize(i)sec = os.path.getmtime(i)...
我们获取当前工作目录的内容,并确定文件扩展名,大小和最后修改时间。
if os.path.isdir(i):self.SetItemImage(j, 1)elif ex == 'py':self.SetItemImage(j, 2)elif ex == 'jpg':self.SetItemImage(j, 3)elif ex == 'pdf':self.SetItemImage(j, 4)else:self.SetItemImage(j, 0)
根据文件扩展名选择文件的图像。
self.splitter = wx.SplitterWindow(self, ID_SPLITTER, style=wx.SP_BORDER)self.splitter.SetMinimumPaneSize(50)p1 = MyListCtrl(self.splitter)p2 = MyListCtrl(self.splitter)self.splitter.SplitVertically(p1, p2)
我们有两个列表控件,这些控件由拆分器小部件垂直拆分。
menuBar = wx.MenuBar()menuBar.Append(filemenu, "&File")menuBar.Append(editmenu, "&Edit")...
我们有一个菜单栏。
tb = self.CreateToolBar( wx.TB_HORIZONTAL | wx.NO_BORDER |wx.TB_FLAT)tb.AddTool(10, 'Previous', wx.Bitmap('images/previous.png'), shortHelp='Previous')tb.AddTool(20, 'Up', wx.Bitmap('images/up.png'), shortHelp='Up one directory')...
我们有一个工具栏。
self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)button1 = wx.Button(self, ID_BUTTON + 1, "F3 View")button2 = wx.Button(self, ID_BUTTON + 2, "F4 Edit")button3 = wx.Button(self, ID_BUTTON + 3, "F5 Copy")button4 = wx.Button(self, ID_BUTTON + 4, "F6 Move")...
八个按钮放置在水平大小调整器中,该大小调整器添加到窗口底部。

图:文件管理器
电子表格
下面的示例创建电子表格应用的 UI。
spreadsheet.py
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""ZetCode wxPython tutorialThis program creates a SpreadSheet UI.author: Jan Bodnarwebsite: zetcode.comlast edited: May 2018"""from wx.lib import sheetimport wxclass MySheet(wx.grid.Grid):def __init__(self, *args, **kw):super(MySheet, self).__init__(*args, **kw)self.InitUI()def InitUI(self):nOfRows = 55nOfCols = 25self.row = self.col = 0self.CreateGrid(nOfRows, nOfCols)self.SetColLabelSize(20)self.SetRowLabelSize(50)self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnGridSelectCell)for i in range(nOfRows):self.SetRowSize(i, 20)for i in range(nOfCols):self.SetColSize(i, 75)def OnGridSelectCell(self, e):self.row, self.col = e.GetRow(), e.GetCol()control = self.GetParent().GetParent().positionvalue = self.GetColLabelValue(self.col) + self.GetRowLabelValue(self.row)control.SetValue(value)e.Skip()class Example(wx.Frame):def __init__(self, *args, **kw):super(Example, self).__init__(*args, **kw)self.InitUI()def InitUI(self):fonts = ['Times New Roman', 'Times', 'Courier', 'Courier New', 'Helvetica','Sans', 'verdana', 'utkal', 'aakar', 'Arial']font_sizes = ['10', '11', '12', '14', '16']box = wx.BoxSizer(wx.VERTICAL)menuBar = wx.MenuBar()menu1 = wx.Menu()menuBar.Append(menu1, '&File')menu2 = wx.Menu()menuBar.Append(menu2, '&Edit')menu3 = wx.Menu()menuBar.Append(menu3, '&Edit')menu4 = wx.Menu()menuBar.Append(menu4, '&Insert')menu5 = wx.Menu()menuBar.Append(menu5, 'F&ormat')menu6 = wx.Menu()menuBar.Append(menu6, '&Tools')menu7 = wx.Menu()menuBar.Append(menu7, '&Data')menu8 = wx.Menu()menuBar.Append(menu8, '&Help')self.SetMenuBar(menuBar)toolbar1 = wx.ToolBar(self, style= wx.TB_HORIZONTAL)toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/new.png'))toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/open.png'))toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/save.png'))toolbar1.AddSeparator()toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/cut.png'))toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/copy.png'))toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/paste.png'))toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/delete.png'))toolbar1.AddSeparator()toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/undo.png'))toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/redo.png'))toolbar1.AddSeparator()toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/asc.png'))toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/desc.png'))toolbar1.AddSeparator()toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/chart.png'))toolbar1.AddSeparator()toolbar1.AddTool(wx.ID_ANY, '', wx.Bitmap('images/exit.png'))toolbar1.Realize()toolbar2 = wx.ToolBar(self, wx.TB_HORIZONTAL | wx.TB_TEXT)self.position = wx.TextCtrl(toolbar2)font = wx.ComboBox(toolbar2, value='Times', choices=fonts, size=(100, -1),style=wx.CB_DROPDOWN)font_height = wx.ComboBox(toolbar2, value='10', choices=font_sizes,size=(50, -1), style=wx.CB_DROPDOWN)toolbar2.AddControl(self.position)toolbar2.AddControl(font)toolbar2.AddControl(font_height)toolbar2.AddSeparator()toolbar2.AddCheckTool(wx.ID_ANY, '', wx.Bitmap('images/text-bold.png'))toolbar2.AddCheckTool(wx.ID_ANY, '', wx.Bitmap('images/text-italic.png'))toolbar2.AddCheckTool(wx.ID_ANY, '', wx.Bitmap('images/text-underline.png'))toolbar2.AddSeparator()toolbar2.AddTool(wx.ID_ANY, '', wx.Bitmap('images/align-left.png'))toolbar2.AddTool(wx.ID_ANY, '', wx.Bitmap('images/align-center.png'))toolbar2.AddTool(wx.ID_ANY, '', wx.Bitmap('images/align-right.png'))box.Add(toolbar1, border=5)box.Add((5,5) , 0)box.Add(toolbar2)box.Add((5,10) , 0)toolbar2.Realize()self.SetSizer(box)notebook = wx.Notebook(self, style=wx.RIGHT)sheet1 = MySheet(notebook)sheet2 = MySheet(notebook)sheet3 = MySheet(notebook)sheet1.SetFocus()notebook.AddPage(sheet1, 'Sheet1')notebook.AddPage(sheet2, 'Sheet2')notebook.AddPage(sheet3, 'Sheet3')box.Add(notebook, 1, wx.EXPAND)self.CreateStatusBar()self.SetSize((550, 550))self.SetTitle("SpreadSheet")self.Centre()def main():app = wx.App()ex = Example(None)ex.Show()app.MainLoop()if __name__ == '__main__':main()
该代码示例创建电子表格应用的 UI。 我有一个菜单栏,工具栏和一个中央网格小部件。
class MySheet(wx.grid.Grid):def __init__(self, *args, **kw):super(MySheet, self).__init__(*args, **kw)self.InitUI()def InitUI(self):nOfRows = 55nOfCols = 25self.row = self.col = 0self.CreateGrid(nOfRows, nOfCols)...
我们创建一个自定义的wx.grid.Grid小部件。 我们的每个工作表将有 55 行和 25 列。 用CreateGrid()方法创建一个单元格网格。
control = self.GetParent().GetParent().position
位置文本控件显示了网格小部件的选定单元格。 它是第二个工具栏的第一个小部件。 在Example类内部,我们需要获取对文本控件的引用,该引用在Example类中定义。 MySheet是笔记本的子项。 笔记本是Example的子项。 因此,通过两次调用GetParent()方法,我们设法到达了位置文本控件。
notebook = wx.Notebook(self, style=wx.RIGHT)sheet1 = MySheet(notebook)sheet2 = MySheet(notebook)sheet3 = MySheet(notebook)sheet1.SetFocus()notebook.AddPage(sheet1, 'Sheet1')notebook.AddPage(sheet2, 'Sheet2')notebook.AddPage(sheet3, 'Sheet3')
将创建三张纸并将其放置在笔记本小部件中。

图:电子表格
播放器
以下示例是典型视频播放器的框架。
player.py
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""ZetCode wxPython tutorialThis program creates a Player UI.author: Jan Bodnarwebsite: zetcode.comlast edited: May 2018"""import wxclass Example(wx.Frame):def __init__(self, *args, **kw):super(Example, self).__init__(*args, **kw)self.InitUI()def InitUI(self):self.CreateMenuBar()panel = wx.Panel(self)pnl1 = wx.Panel(self)pnl1.SetBackgroundColour(wx.BLACK)pnl2 = wx.Panel(self)slider1 = wx.Slider(pnl2, value=18, minValue=0, maxValue=1000)pause = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/pause.png'))play = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/play.png'))forw = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/forw.png'))back = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/back.png'))vol = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/volume.png'))slider2 = wx.Slider(pnl2, value=1, minValue=0, maxValue=100,size=(120, -1))vbox = wx.BoxSizer(wx.VERTICAL)hbox1 = wx.BoxSizer(wx.HORIZONTAL)hbox2 = wx.BoxSizer(wx.HORIZONTAL)hbox1.Add(slider1, proportion=1)hbox2.Add(pause)hbox2.Add(play, flag=wx.RIGHT, border=5)hbox2.Add(forw, flag=wx.LEFT, border=5)hbox2.Add(back)hbox2.Add((-1, -1), proportion=1)hbox2.Add(vol)hbox2.Add(slider2, flag=wx.TOP|wx.LEFT, border=5)vbox.Add(hbox1, flag=wx.EXPAND|wx.BOTTOM, border=10)vbox.Add(hbox2, proportion=1, flag=wx.EXPAND)pnl2.SetSizer(vbox)sizer = wx.BoxSizer(wx.VERTICAL)sizer.Add(pnl1, proportion=1, flag=wx.EXPAND)sizer.Add(pnl2, flag=wx.EXPAND|wx.BOTTOM|wx.TOP, border=10)self.SetMinSize((350, 300))self.CreateStatusBar()self.SetSizer(sizer)self.SetSize((350, 200))self.SetTitle('Player')self.Centre()def CreateMenuBar(self):menubar = wx.MenuBar()filem = wx.Menu()play = wx.Menu()view = wx.Menu()tools = wx.Menu()favorites = wx.Menu()help = wx.Menu()filem.Append(wx.ID_ANY, '&Quit', 'Quit application')menubar.Append(filem, '&File')menubar.Append(play, '&Play')menubar.Append(view, '&View')menubar.Append(tools, '&Tools')menubar.Append(favorites, 'F&avorites')menubar.Append(help, '&Help')self.SetMenuBar(menubar)def main():app = wx.App()ex = Example(None)ex.Show()app.MainLoop()if __name__ == '__main__':main()
为了构建界面,我们使用了位图按钮,滑块,面板和菜单栏。
pnl1 = wx.Panel(self)pnl1.SetBackgroundColour(wx.BLACK)
应用的主要区域由黑色背景的面板占据。
slider1 = wx.Slider(pnl2, value=18, minValue=0, maxValue=1000)
wx.Slider用于显示胶片的进度。
pause = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/pause.png'))play = wx.BitmapButton(pnl2, bitmap=wx.Bitmap('images/play.png'))
位图按钮用于控制按钮。
self.SetMinSize((350, 300))
在这里,我们设置播放器的最小大小。 将窗口缩小到某个值以下没有太大意义。

图:播放器
浏览器
在下面的示例中,我们模仿经典浏览器 UI 的外观。
browser.py
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""ZetCode wxPython tutorialThis program creates a browser UI.author: Jan Bodnarwebsite: zetcode.comlast edited: May 2018"""import wxfrom wx.lib.buttons import GenBitmapTextButtonclass Example(wx.Frame):def __init__(self, *args, **kw):super(Example, self).__init__(*args, **kw)self.InitUI()def InitUI(self):self.CreateMenuBar()panel = wx.Panel(self)# panel.SetBackgroundColour('white')vbox = wx.BoxSizer(wx.VERTICAL)hbox1 = wx.BoxSizer(wx.HORIZONTAL)hbox2 = wx.BoxSizer(wx.HORIZONTAL)line1 = wx.StaticLine(panel)vbox.Add(line1, 0, wx.EXPAND)toolbar1 = wx.Panel(panel, size=(-1, 30))back = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/back.png'),style=wx.NO_BORDER)forward = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/forw.png'),style=wx.NO_BORDER)refresh = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/refresh.png'),style=wx.NO_BORDER)stop = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/stop.png'),style=wx.NO_BORDER)home = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/home.png'),style=wx.NO_BORDER)address = wx.ComboBox(toolbar1, size=(50, -1))go = wx.BitmapButton(toolbar1, bitmap=wx.Bitmap('images/play.png'),style=wx.NO_BORDER)text = wx.TextCtrl(toolbar1, size=(150, -1))hbox1.Add(back)hbox1.Add(forward)hbox1.Add(refresh)hbox1.Add(stop)hbox1.Add(home)hbox1.Add(address, 1, wx.TOP, 3)hbox1.Add(go, 0, wx.TOP | wx.LEFT, 3)hbox1.Add(text, 0, wx.TOP | wx.RIGHT, 3)toolbar1.SetSizer(hbox1)vbox.Add(toolbar1, 0, wx.EXPAND)line = wx.StaticLine(panel)vbox.Add(line, 0, wx.EXPAND)toolbar2 = wx.Panel(panel, size=(-1, 30))bookmark1 = wx.BitmapButton(toolbar2, bitmap=wx.Bitmap('images/love.png'),style=wx.NO_BORDER)bookmark2 = wx.BitmapButton(toolbar2, bitmap=wx.Bitmap('images/book.png'),style=wx.NO_BORDER)bookmark3 = wx.BitmapButton(toolbar2, bitmap=wx.Bitmap('images/sound.png'),style=wx.NO_BORDER)hbox2.Add(bookmark1, flag=wx.RIGHT, border=5)hbox2.Add(bookmark2, flag=wx.RIGHT, border=5)hbox2.Add(bookmark3)toolbar2.SetSizer(hbox2)vbox.Add(toolbar2, 0, wx.EXPAND)line2 = wx.StaticLine(panel)vbox.Add(line2, 0, wx.EXPAND)panel.SetSizer(vbox)self.CreateStatusBar()self.SetTitle("Browser")self.Centre()def CreateMenuBar(self):menubar = wx.MenuBar()file = wx.Menu()file.Append(wx.ID_ANY, '&Quit', '')edit = wx.Menu()view = wx.Menu()go = wx.Menu()bookmarks = wx.Menu()tools = wx.Menu()help = wx.Menu()menubar.Append(file, '&File')menubar.Append(edit, '&Edit')menubar.Append(view, '&View')menubar.Append(go, '&Go')menubar.Append(bookmarks, '&Bookmarks')menubar.Append(tools, '&Tools')menubar.Append(help, '&Help')self.SetMenuBar(menubar)def main():app = wx.App()ex = Example(None)ex.Show()app.MainLoop()if __name__ == '__main__':main()
为了创建一个较大的组合框,我们不能使用wx.Toolbar。 我们基于wx.Panel创建自定义工具栏。
toolbar1 = wx.Panel(panel, size=(-1, 40))
我们创建一个普通的wx.Panel。
hbox1 = wx.BoxSizer(wx.HORIZONTAL)...hbox1.Add(back)hbox1.Add(forward)hbox1.Add(refresh)
我们创建一个水平大小调整器,并添加所有必要的按钮。
hbox1.Add(address, 1, wx.TOP, 4)
然后,将组合框添加到大小调整器。 这种组合框通常称为地址栏。 请注意,这是唯一将比例设置为 1 的小部件。这是使其可调整大小的必要条件。
line2 = wx.StaticLine(panel)vbox.Add(line2, 0, wx.EXPAND)
工具栏由一行分隔。

图:浏览器 UI
在 wxPython 教程的这一部分中,我们创建了一些应用框架。
