# 第十二章 圖形用戶界面
> 來源:http://www.cnblogs.com/Marlowes/p/5520948.html
> 作者:Marlowes
本章將會介紹如何創建Python程序的圖形用戶界面(GUI),也就是那些帶有按鈕和文本框的窗口等。很酷吧?
目前支持Python的所謂“GUI工具包”(GUI Toolkit)有很多,但是沒有一個被認為是標注你的GUI工具包。這樣的情況也好(自由選擇的空間較大)也不好(其他人沒法用程序,除非他們也安裝了相同的GUI工具包),幸好Python的GUI工具包之間沒有沖突,想裝多少個就可以裝多少個。
本章簡要介紹最成熟的跨平臺Python GUI工具包——wxPython。有關更多wxPython程序的介紹,請參考[官方文檔](http://wxpython.org)。關于GUI程序設計的更多信息請參見第二十八章。
## 12.1 豐富的平臺
在編寫Python GUI程序前,需要決定使用哪個GUI平臺。簡單來說,平臺是圖形組件的一個特定集合,可以通過叫做GUI工具包的給定Python模塊進行訪問。Python可用的工具包很多。其中一些最流行的如表12-1所示。要獲取更加詳細的列表,可以在[Vaults of Parnassus](http://py.vaults.ca/)上面以關鍵字"GUI"進行搜索。也可以在[Python Wiki](http://wiki.python.org/moin/GuiProgramming)上找到完全的工具列表。Guiherme Polo也撰寫過一篇有關4個主要平臺對比的論文("PyGTK,PyQt,Tkinter and wxPython comparison"(PyGTK、PyQt、Tkinter和wxPython的比較),The Python Papers, 卷3,第1期26~37頁。這篇文章可以從 http://pythonpapers.org 上獲得)。
表12-1 一些支持Python的流行GUI工具包
```
Tkinter 使用Tk平臺,很容易得到,半標準。 http://wiki.python.org/moin/TkInter
wxpython 基于wxWindows,跨平臺越來越流行。 http://wxpython.org
PythonWin 只能在Windows上使用,使用了本機的Windows GUI功能 http://starship.python.net/crew/mhammond
Java Swing 只能用于Jython,使用本機的Java GUI。 http://java.sun.com/docs/books/tutorial/uiswing
PyGTK 使用GTK平臺,在Linux上很流行。 http://pygtk.org
PyQt 使用Qt平臺,跨平臺。 http://wiki.python.org/moin/PyQt
```
可選的包太多了,那么應該用哪個呢?盡管每個工具包都有利弊,但很大程度上取決于個人喜好。Tkinter實際上類似于標準,因為它被用于大多數“正式的”Python GUI程序,而且它是Windows二進制發布版的一部分。但是在UNIX上要自己編譯安裝。Tkinter和Swing Jython將在12.4節進行介紹。
另外一個越來越受歡迎的工具是wxPython。這是個成熟而且特性豐富的包,也是Python之父Guido van Rossum的最愛。在本章的例子中,我們將使用wxPython。
關于Pythonwin、PyGTK和PyQt的更多信息,請查看這些項目的主頁(見表12-1)。
## 12.2 下載和安裝wxPython
要下載wxPython,只要訪問它的[下載頁面](http://wxpython.org/download.php)即可。這個網頁提供了關于下載哪個版本的詳細指導,還有使用不同版本的先決條件。
如果使用Windows系統,應該下載預建的二進制版本。可以選擇支持Unicode或不支持Unicode的版本,除非要用到Unicode,否則選擇哪個版本區別并不大。確保所選擇的二進制版本要對應Python的版本。例如,針對Python2.3進行編譯的wxPython并不能用于Python2.4。
對于Mac OS X來說,也應該選擇對應Python版本的wxPython。可能還需要考慮操作系統版本。同樣,你也可以選擇支持Unicode和不支持Unicode的版本。下載鏈接和相關的解釋能非常明確地告訴你應該下載哪個版本。
如果讀者正在使用Linux,那么可以查看包管理器中是否包括wxPython,它存在于很多主流發布版本中。對于不同版本的Linux來說也有不同的RPM包。如果運行包含RPM的Linux發行版,那么至少應該下載wxPython和運行時包(runtime package),而不需要devel包。再說一次,要選擇與Python以及Linux發布版對應的版本。
如果沒有任何版本適合硬件或操作系統(或者Python版本),可以下載源代碼發布版。為了編譯可能還需要根據各種先決條件下載其他的源代碼包,這已經超出了本章的范圍。這些內容在wxPython的下載頁面上都有詳細的解釋。
在下載了wxPython之后,強烈建議下載演示版本(demo,它必須進行獨立安裝),其中包含文檔、示例程序和非常詳細的(而且有用的)演示分布。這個演示程序演示了大多數wxPython的特性,并且還能以對用戶非常友好的方式查看各部分源代碼——如果想要自學wxPython的話非常值得一看。
安裝過程應該很簡單,而且是自動完成的。安裝Windows二進制版本只要運行下載完的可執行文件(.exe文件);在OS X系統中,下載后的文件應該看起來像是可以打開的CD-ROM一樣,并帶有一個可以雙擊的.pkg文件。要使用RPM安裝,請參見RPM文檔。Windows和Mac OS X版本都會運行一個安裝向導,用起來很簡單。只要選擇默認設置即可,然后一直惦記Continue,最后點擊Finish即可。
## 12.3 創建示例GUI應用程序
為使用wxPython進行演示,首先來看一下如何創建一個簡單的示例GUI應用程序。你的任務是編寫一個能編輯文本文件的基礎程序。編寫全功能的文本編輯器已經超出了本章的范圍——關注的只是基礎。畢竟目標是演示在Python中進行GUI編程的基本原理。
對這個小型文本編輯器的功能要求如下:
? 它應允許打開給定文件名的文本文件;
? 它應允許編輯文本文件;
? 它應允許保存文本文件;
? 它應允許退出程序。
當編寫GUI程序時,畫個界面草圖總是有點用的。圖12-1展示了一個滿足我們文本編輯要求的布局:
圖12-1 文本編輯器草圖

界面元素可以像下面這樣使用。
? 在按鈕左側的文本框內輸入文件名,點擊Open打開文件。文件中包含的文本會顯示在下方的文本框內。
? 可以在這個大的文本框中隨心所欲地編輯文本。
? 如果希望保存修改,那么點擊Save按鈕,會再次用到包含文件名的文本框——然后將文本框的內容寫入文件。
? 沒有Quit(退出)按鈕——如果用戶關閉窗口,程序就會退出。
使用某些語言寫這樣的程序時相當難的。但是利用Python和恰當的GUI工具包,簡直是小菜一碟(雖然現在讀者可能不同意這種說法,但在學習完本章之后應該就會同意了)。
### 12.3.1 開始
為了查看wxPython是否能工作,可以嘗試運行wxPython的演示版本(要單獨安裝)。Windows內應該可以在開始菜單找到,而OS X可以直接把wxPython Demo文件拖到應用程序中,然后運行。看夠了演示就可以開始寫自己的程序了,當然,這會更有趣的。
開始需要導入`wx`模塊:
```
import wx
```
編寫wxPython程序的方法很多,但不可避免的事情是創建應用程序對象。基本的應用程序類叫做ex.App,它負責幕后所有的初始化。最簡單的wxPython程序應該像下面這樣:
```
import wx
app = wx.App()
app.MainLoop()
```
注:如果`wx.App`無法工作,可能需要將它替換為`wx.PySimpleApp`。
因為沒有任何用戶可以交互的窗口,程序會立刻退出。
例中可以看到,`wx`包中的方法都是以大寫字母開頭的,而這和Python的習慣是相反的。這樣做的原因是這些方法名和基礎的C++包wxWidgets中的方法名都是對應的。盡管沒有正式的規則反對方法或者函數名以大寫字母開頭,但是規范的做法是為類保留這樣的名字。
### 12.3.2 窗口和組件
窗口(Windows)也成為_框架_(`frame`),它只是`wx.Frame`類的實例。`wx`框架中的部件都是由它們的_父部件_作為構造函數的第一個參數創建的。如果正在創建一個單獨的窗口,就不需要考慮父部件,使用None即可,如代碼清單12-1所示。而且在調用`app.MainLoop`前需要調用窗口的`Show`方法——否則它會一直隱藏(可以在事例處理程序中調用`win.Show`,后面會介紹)。
```
# 代碼清單12-1 創建并且顯示一個框架
import wx
app = wx.App()
win = wx.Frame(None)
win.Show()
app.MainLoop()
```
如果運行這個程序,應該能看到一個窗口出現,類似于圖12-2。
圖12-2 只有一個窗口的GUI程序

在框架上增加按鈕也很簡單——只要使用win作為符參數實例化`wx.Button`即可,如代碼清單12-2所示。
```
# 代碼清單12-2 在框架上增加按鈕
import wx
app = wx.App()
win = wx.Frame(None)
btn = wx.Button(win)
win.Show()
app.MainLoop()
```
這樣會得到一個帶有一個按鈕的窗口,如圖12-3所示。
圖12-3 增加按鈕后的程序

當然,這里做的還不夠,窗口沒有標題,按鈕沒有標簽,而且也不希望讓按鈕覆蓋整個窗口。
### 12.3.3 標簽、標題和位置
可以在創建部件的時候使用構造函數的label參數設定它們的標簽。同樣,也可以用`title`參數設定框架的標題。我發現最實用的做法是為`wx`構造函數使用關鍵字參數,所以我不用記住參數的順序。代碼清單12-3演示了一個例子。
```
# 代碼清單12-3 使用關鍵字參數增加標簽和標題
import wx
app = wx.App()
win = wx.Frame(None, title="Simple Editor")
loadButton = wx.Button(win, label="Open")
saveButton = wx.Button(win, label="Save")
win.Show()
app.MainLoop()
```
程序的運行結果如圖12-4所示。
這個版本的程序還是有些不對——好像丟了一個按鈕!實際上它沒丟——只是隱藏了。注意一下按鈕的布局就能將隱藏的按鈕顯示出來。一個很基礎(但是不實用)的方法是使用pos和size參數在構造函數內設置位置和尺寸,如代碼清單12-4所示。
12-4 有布局問題的窗口

```
# 代碼清單12-4 設置按鈕位置
import wx
app = wx.App()
win = wx.Frame(None, title="Simple Editor", size=(410, 335))
win.Show()
loadButton = wx.Button(win, label="Open",
pos=(225, 5), size=(80, 25))
saveButton = wx.Button(win, label="Save",
pos=(315, 5), size=(80, 25))
filename = wx.TextCtrl(win, pos=(5, 5), size=(210, 25))
contents = wx.TextCtrl(win, pos=(5, 35), size=(390, 260),
style=wx.TE_MULTILINE | wx.HSCROLL)
app.MainLoop()
```
你看到了,位置和尺寸都包括一對數值:位置包括x和y坐標,而尺寸包括寬和高。
這段代碼中還有一些新東西:我創建了兩個_文本控件_(`text control`,`wx.TextCtrl`對象),每個都使用了自定義風格。默認的文本控件是_文本框_(text field),就是一行可編輯的文本,沒有滾動條,為了創建_文本區_(text area)只要使用`style`參數調整風格即可。`style`參數的值實際上是個整數,但不用直接指定,可以使用按位或運算符OR(或管道運算符)聯合`wx`模塊中具有特殊名字的風格來指定。本例中,我聯合了`wx.TE_MULTILINE`來獲取多行文本區(默認有垂直滾動條)以及`wx.HSCROLL`來獲取水平滾動條。程序運行的結果如圖12-5所示。
圖12-5 位置合適的組件

### 12.3.4 更智能的布局
盡管明確每個組件的幾何位置很容易理解,但是過程很乏味。在繪圖紙上畫出來可能有助于確定坐標,但是用數字來調整位置的方法有很多嚴重的缺點。如果運行程序并且試圖調整窗口大小,那么會注意到組件的幾何位置不變。雖然不是什么大事,但是看起來還是有些奇怪。在調整窗口大小時,應該能保證窗口中的組件也會隨之調整大小和位置。
考慮一下我是如何布局的,那么出現這種情況就不會令人驚訝了。每個組件的位置和大小都顯式設定的,但是沒有明確在窗口大小變化的時候它們的行為是什么。指定行為的方法有很多,在wx內進行布局的最簡單方法是使用_尺寸器_(sizer),最容易使用的工具就是`wx.BoxSizer`。
尺寸器會管理組件的尺寸。只要將部件添加到尺寸器上,再加上一些布局參數,然后讓尺寸器自己去管理父組件的尺寸。在剛才的例子中,需要增加背景組件(`wx.Panel`),創建一些嵌套的`wx.BoxSizer`,然后使用面板的`SetSizer`方法設定它的尺寸器,如代碼清單12-5所示。
```
import wx
app = wx.App()
win = wx.Frame(None, title="Simple Editor", size=(410, 335))
bkg = wx.Panel(win)
loadButton = wx.Button(bkg, label="open")
saveButton = wx.Button(bkg, label="Save")
filename = wx.TextCtrl(bkg)
contents = wx.TextCtrl(bkg, style=wx.TE_MULTILINE | wx.HSCROLL)
hbox = wx.BoxSizer()
hbox.Add(filename, proportion=1, flag=wx.EXPAND)
hbox.Add(loadButton, proportion=0, flag=wx.LEFT, border=5)
hbox.Add(saveButton, proportion=0, flag=wx.LEFT, border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
vbox.Add(contents, proportion=1,
flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, border=5)
bkg.SetSizer(vbox)
win.Show()
app.MainLoop()
```
這段代碼的運行結果和前例相同,但是使用了相對坐標而不是絕對坐標。
`wx.BoxSizer`的構造函數帶有一個決定它是水平還是垂直的參數(`wx.HORIZONTAL`或者`wx.VERTICAL`),默認為水平。`Add`方法有幾個參數,`proportion`參數根據在窗口改變大小時所分配的空間設置比例。例如,水平的`BoxSizer`(第一個)中,`filename`組件在改變大小時獲取了全部的額外空間。如果這3個部件都把`proportion`設為1,那么都會獲得相等的空間。可以將`proportion`設定為任何數。
`flag`參數類似于構造函數中的`style`參數,可以使用按位或運算符連接構造符號常量(`symbolic constan`t,即有特殊名字的整數)對其進行構造。`wx.EXPAND`標記確保組件會擴展到所分配的空間中。而`wx.LEFT`、`wx.RIGHT`、`wx.TOP`、`wx.BOTTOM`和`wx.ALL`標記決定邊框參數應用于哪個邊,邊框參數用于設置邊緣寬度(間隔)。
就是這樣。我得到了我要的布局。但是遺漏了一件至關重要的事情——按下按鈕,卻什么都沒發生。
_注:更多有關尺寸器的信息或者與wxPython相關的信息請參見wxPython的演示版本,它里面會有你想要了解的內容和示例代碼。如果看起來比較難,可以訪問[wxPython的網站](http://wxpython.org)。_
### 12.3.5 事件處理
在GUI術語中,用戶執行的動作(比如點擊按鈕)叫做_事件_(event)。你需要讓程序注意這些事件并且做出反應。可以將函數綁定到所涉及的時間可能發生的組件上達到這個效果。當事件發生時,函數會被調用。利用部件的Bind方法可以將時間處理函數鏈接到給定的事件上。
假設寫了一個負責打開文件的函數,并將其命名為`load`。然后就可以像下面這樣將該函數作為loadButton的事件處理函數:
```
loadButton.Bind(wx.EVT_BUTTON, load)
```
很直觀,不是嗎?我把函數鏈接到了按鈕——點擊按鈕的時候,函數被調用。名為`wx.EVT_BUTTON`的符號常量表示一個_按鈕事件_。`wx`框架對于各種事件都有這樣的事件常量——從鼠標動作到鍵盤按鍵,等等。
為什么用LOAD?
_注:我之所以用`loadButton`和`load`作為按鈕以及處理函數的名字不是偶然的——盡管按鈕的文本為`"Open"`。這是因為如果我把按鈕叫做`openButton`的話,`open`也就自然成了事件處理函數的名字,這樣就和內建的文件打開函數`open`沖突,導致后者失效。雖然有很多種方法可以解決這個問題,但我覺得使用不同的名字是最簡單的。_
### 12.3.6 完成了的程序
讓我們來完成剩下的工作。現在需要的就是兩個事件處理函數:`load`和`save`。當事件處理函數被調用時,它會收到一個事件對象作為它唯一的參數,其中包括發生了什么事情的信息,但是在這里可以忽略這方面的事情,因為程序只關心點擊時發生的事情。
```
def load(event):
file = open(filename.GetValue())
contents.SetValue(file.read())
file.close()
```
讀過第十一章后,讀者應該對于文件打開/讀取的部分比較熟悉了。文件名使用`filename`對象的`GetValue`方法獲取(`filename`是小的文本框)。同樣,為了將文本引入文本區,只要使用`contents.SetValue`即可。
`save`函數也很簡單:幾乎和`load`一樣——除了它有個`"w"`標志,以及用于文件處理部分的`write`方法。`GetValue`用于從文本區獲得信息。
```
def save(event):
file = open(filename.GetValue(), "w")
file.write(contents.GetValue())
file.close()
```
就是這樣了。現在我將這些函數綁定到相應的按鈕上,程序已經可以運行了。最終的程序如代碼清單12-6所示。
```
#!/usr/bin/env python # coding=utf-8
import wx def load(event):
file = open(filename.GetValue())
contents.SetValue(file.read())
file.close() def save(event):
file = open(filename.GetValue(), "w")
file.write(contents.GetValue())
file.close()
app = wx.App()
win = wx.Frame(None, title="Simple Editor", size=(410, 335))
bkg = wx.Panel(win)
loadButton = wx.Button(bkg, label="open")
loadButton.Bind(wx.EVT_BUTTON, load)
saveButton = wx.Button(bkg, label="Save")
saveButton.Bind(wx.EVT_BUTTON, save)
filename = wx.TextCtrl(bkg)
contents = wx.TextCtrl(bkg, style=wx.TE_MULTILINE | wx.HSCROLL)
hbox = wx.BoxSizer()
hbox.Add(filename, proportion=1, flag=wx.EXPAND)
hbox.Add(loadButton, proportion=0, flag=wx.LEFT, border=5)
hbox.Add(saveButton, proportion=0, flag=wx.LEFT, border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
vbox.Add(contents, proportion=1,
flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, border=5)
bkg.SetSizer(vbox)
win.Show()
app.MainLoop()
```
`GUI.py`
可以按照下面的步驟使用這個編輯器。
(1) 運行程序。應該看到一個和剛才差不多的窗口。
(2) 在文本區里面打些字(比如`"Hello, world!"`)
(3) 在文本框中鍵入文件名(比如`hello.txt`)。確保文件不存在,否則它會被覆蓋。
(4) 點擊`Save`按鈕。
(5) 關閉編輯窗口(只為了好玩)。
(6) 重啟程序。
(7) 在文本框內鍵入同樣的文件名。
(8) 點擊`Open`按鈕。文件的文本內容應該會在大文本區內重現。
(9) 隨便編輯一下文件,再次保存。
現在可以打開、編輯和保存文件,直到感到煩為止——然后應該考慮一下改進。例如使用`urllib`模塊讓程序下載文件怎么樣?
讀者可能會考慮在程序中使用更加面向對象的設計。例如,可能希望將主應用程序作為自定義應用程序類(可能是`wx.App`的子類)的一個實例進行管理,而不是將整個結構置于程序的最頂層。也可以創建一個單獨的窗口類(`wx.Frame`的子類)。請參見第28章獲取更多示例。
**PYW怎么樣**
在Windows中,你可以使用`.pyw`作為文件名的結尾來保存GUI程序。在第一章中,我告訴給你的文件名使用這個結尾然后雙擊它(Windows中),什么都沒發生,之后我保證我會在后面解釋。在第十章中,我再次提到了這個是,并且說本章內會解釋,所以現在就說說吧。
其實沒什么大不了的。在Windows中雙擊普通的Python腳本時,會出現一個帶有Python提示符的DOS窗口,如果使用`print`和`raw_input`作為基礎界面,那么就沒問題。但是現在已經知道如何創建GUI程序了,DOS窗口就顯得有些多余,`pyw`窗口背后的真相就是它可以在沒有DOS窗口的情況下運行Python——對于GUI程序就完美了。
## 12.4 但是我寧愿用······
Python的GUI工具包是在太多,所以我沒辦法將所有工具包都展示給你看。不過我可以給出一些流行的GUI包中的例子(比如Tkinter和Jython/Swing)。
為了演示不同的包,我創建了一個簡單的程序——很簡單,比剛才的編輯器例子還簡單。只有一個窗口,該窗口包含一個帶有`"Hello"`標簽的按鈕。當點擊按鈕時,它會打印出文本`"Hello, world!"`,為了簡單,我沒有使用任何特殊的布局特性。下面是一個wxPython版本的示例。
```
import wx
def hello(event):
print "Hello, world!"
app = wx.App()
win = wx.Frame(None, title="Hello, wxPython!",
size=(200, 100))
button = wx.Button(win, label="Hello")
button.Bind(wx.EVT_BUTTON, hello)
win.Show()
app.MainLoop()
```
最終的結果如圖12-6所示。
圖12-6 簡單的GUI示例

### 12.4.1 使用Tkinter
Tkinter是個老牌的Python GUI程序。它由Tk GUI工具包(用于Tcl編程語言)包裝而來。默認在Windows版和Mac OS發布版中已經包括。下面的網址可能有用:
? http://www.ibm.com/developerworks/linux/library/l-tkprg
? http://www.nmt.edu/tcc/help/lang/python/tkinter.pdf
下面是使用Tkinter實現的GUI程序。
```
from Tkinter import *
def hello():
print "Hello, world!"
# Tkinter的主窗口
win = Tk()
win.title("Hello, Tkinter!")
# Size 200, 100
win.geometry("200x100")
btn = Button(win, text="Hello", command=hello)
btn.pack(expand=YES, fill=BOTH)
mainloop()
```
### 12.4.2 使用Jython和Swing
如果正在使用Jython(Python的Java實現),類似wxPython和Tkinter這樣的包就不能用了。唯一可用的GUI工具包是Java標準庫包AWT和Swing(Swing是最新的,而且被認為是標準的Java GUI工具包)。好消息是兩者都直接可用,不用單獨安裝。更多信息,請訪問Java的網站,以及為Java而寫的Swing文檔:
? http://www.jython.org
? http://java.sun.com/docs/books/tutorial/uiswing
下面是使用Jython和Swing實現的GUI示例。
```
from javax.swing import *
import sys
def hello(event):
print "Hello, world!"
btn = JButton("Hello")
btn.actionPerformed = hello
win = JFrame("Hello, Swing!")
win.contentPane.add(btn)
def closeHandler(event):
sys.exit()
win.windowClosing = closeHandler
btn.size = win.size = 200, 100
win.show()
```
注意,這里增加了一個額外的事件處理函數(`closeHandler`),因為關閉按鈕Java Swing中沒有任何有用的默認行為。另外,無須顯式地進入主事件循環,因為它是和程序并行運行的(在不同的線程中)。
### 12.4.3 使用其他開發包
大多數GUI工具包的基礎都一樣,不過遺憾的是當學習如何使用一個新的包時,通過使你能做成想做的事情的所有細節而找到學習新包的方法還是很花時間的。所以在決定使用哪個包(12.1節應該對從何處著手有些幫助)之前應該花上些時間考慮,然后就是泡在文檔中,寫代碼。希望本章能提供了那些理解文檔時需要的基礎概念。
## 12.5 小結
再來回顧一下本章講了什么。
? 圖形用戶界面(GUI):GUI可以讓程序更友好。雖然并不是所有的程序都需要它們,但是當程序要和用戶交互時,GUI可能會有所幫助。
? Python的GUI平臺:Python程序員有很多GUI平臺可用。盡管有這么多選擇是好事,但是選擇時有時會很困難。
? wxPython:wxPython是成熟的并且特色豐富的跨平臺的Python GUI工具包。
? 布局:通過指定幾何坐標,可以直接將組件放置在想要的位置。但是,為了在包含它們的窗口改變大小時能做出適當的改變,需要使用布局管理器。wxPython中的布局機制是_尺寸器_。
? 事件處理:用戶的動作觸發GUI工具包的_事件_。任何應用中,程序都會有對這些事件的反應,否則用戶就沒法和程序交互了。wxPython中事件處理函數使用`Bind`方法添加到組件上。
**接下來學什么**
本章內容就是這樣了。已經學習完了如何編寫通過文件和GUI與外部世界交互的程序。下一章將會介紹另外一個很多程序系統都具有的重要組件:數據庫。