1. 程式人生 > >Python例項講解 -- wxpython 基本的控制元件 (文字)

Python例項講解 -- wxpython 基本的控制元件 (文字)

wxPython 工具包提供了多種不同的視窗部件,包括了本章所提到的基本控制元件。我們涉及靜態文字、可編輯的文字、按鈕、微調、滑塊、複選框、單選按鈕、選擇器、列表框、組合框和標尺。對於每種視窗部件,我們將提供一個關於如何使用它的簡短例子,並附上相關的wxPython API 的說明。

顯示文字

這一節以在螢幕上顯示文字的例子作為開始,包括用作標籤的靜態文字域,有樣式和無樣式的都使用了。你可以建立用於使用者輸入的單行和多行文字域。另外,我們將討論如何選擇文字的字型。

如何顯示靜態文字?

大概對於所有的UI 工具來說,最基本的任務就是在螢幕上繪製純文字。在wxPython 中,使用類wx.StaticText

 來完成。圖7.1顯示了這個靜態文字控制元件。

w7.1.gif

wx.StaticText 中,你能夠改變文字的對齊方式、字型和顏色。簡單的靜態文字控制元件可以包含多行文字,但是你不能處理多種字型或樣式。處理多種字型或樣式,要使用更精細的文字控制元件,如wx.html.HTMLWindow ,它在第十六章中說明。為了在靜態文字控制元件中顯示多行文字,我們要包括其中有換行符的字串,並使控制元件的大小足夠顯示所有的文字。有一個特點是你在圖7.1中所不能看到的,那就是wx.StaticText 視窗不會接受或響應滑鼠事件。

如何顯示靜態文字

例子7.1顯示了產生圖7.1的程式碼。

例7.1 如何使用靜態文字的一個基本例子

Python程式碼  收藏程式碼
  1. import wx  
  2. class StaticTextFrame(wx.Frame):  
  3.     def __init__(self):  
  4.         wx.Frame.__init__(selfNone, -1'Static Text Example',   
  5.                 size=(400300))  
  6.         panel = wx.Panel(self, -1)  
  7.         # 這是一個基本的靜態文字  
  8.         wx.StaticText(panel, -1"This is an example of static text"
    ,   
  9.                 (10010))  
  10.         # 指定了前景色和背景色的靜態文字  
  11.         rev = wx.StaticText(panel, -1"Static Text With Reversed Colors",   
  12.                 (10030))  
  13.         rev.SetForegroundColour('white')  
  14.         rev.SetBackgroundColour('black')  
  15.         # 指定居中對齊的的靜態文字  
  16.         center = wx.StaticText(panel, -1"align center", (10050),   
  17.                 (160, -1), wx.ALIGN_CENTER)  
  18.         center.SetForegroundColour('white')  
  19.         center.SetBackgroundColour('black')  
  20.         # 指定右對齊的靜態文字  
  21.         right = wx.StaticText(panel, -1"align right", (10070),   
  22.                 (160, -1), wx.ALIGN_RIGHT)  
  23.         right.SetForegroundColour('white')  
  24.         right.SetBackgroundColour('black')  
  25.         # 指定新字型的靜態文字  
  26.         str = "You can also change the font."  
  27.         text = wx.StaticText(panel, -1, str, (20100))  
  28.         font = wx.Font(18, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)  
  29.         text.SetFont(font)  
  30.         # 顯示多行文字  
  31.         wx.StaticText(panel, -1"Your text\ncan be split\n"  
  32.                 "over multiple lines\n\neven blank ones", (20,150))  
  33.         #顯示對齊的多行文字  
  34.         wx.StaticText(panel, -1"Multi-line text\ncan also\n"  
  35.                 "be right aligned\n\neven with a blank", (220,150),   
  36.                 style=wx.ALIGN_RIGHT)  
  37. if __name__ == '__main__':  
  38.     app = wx.PySimpleApp()  
  39.     frame = StaticTextFrame()  
  40.     frame.Show()  
  41.     app.MainLoop()  
 

wx.StaticText 的建構函式和基本的wxWidget 建構函式相同,如下所示:

Python程式碼  收藏程式碼
  1. wx.StaticText(parent, id, label, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="staticText")  
 

表7.1說明了這些引數——大多數的wxPython 視窗部件都有相類似的引數。對於建構函式的引數的更詳細的說明,請參見第2章的相關論述。

表7.1 wx.StaticText 建構函式的引數

parent :父視窗部件。

id :識別符號。使用-1可以自動建立一個唯一的標識。

label :你想顯示在靜態控制元件中的文字。

pos :一個wx.Point 或一個Python 元組,它是視窗部件的位置。

size :一個wx.Size 或一個Python 元組,它是視窗部件的尺寸。

style :樣式標記。

name :物件的名字,用於查詢的需要。

接下來我們更詳細地討論樣式標記。

使用樣式工作

所有在例7.1中靜態文字例項所呼叫的方法都是屬於基父類wx.Window 的;wx.StaticText 沒有定義任何它自己的新方法。表7.2列出了一些專用於wx.StaticText 的樣式。

表7.2

wx.ALIGN_CENTER :靜態文字位於靜態文字控制元件的中心。

wx.ALIGN_LEFT :文字在視窗部件中左對齊。這是預設的樣式。

wx.ALIGN_RIGHT :文字在視窗部件中右對齊。

wx.ST_NO_AUTORESIZE :如果使用了這個樣式,那麼在使用了SetLabel() 改變文字之後,靜態文字控制元件不將自我調整尺寸。你應結合使用一個居中或右對齊的控制元件來保持對齊。

wx.StaticText 控制元件覆蓋了SetLabel() ,以便根據新的文字來調整自身,除非wx.ST_NO_AUTORESIZE 樣式被設定了。

當建立了一個居中或右對齊的單行靜態文字時,你應該顯式地在構造器中設定控制元件的尺寸。指定尺寸以防止wxPython 自動調整該控制元件的尺寸。wxPython 的預設尺寸是剛好包容了文字的矩形尺寸,因此對齊就沒有什麼必要。要在程式中動態地改變視窗部件中的文字,而不改變該視窗部件的尺寸,就要設定wx.ST_NO_AUTORESIZE 樣式。這樣就防止了在文字被重置後,視窗部件自動調整尺寸到剛好包容了文字。如果靜態文字是位於一個動態的佈局中,那麼改變它的尺寸可能導致螢幕上其它的視窗部件移動,這就對使用者產生了干擾。

其它顯示文字的技術

還有其它的方法來顯示文字。其中之一就是wx.lib.stattext.GenStaticText 類,它是wx.StaticText 的純Python實現。它比標準C++版的跨平臺性更好,並且它接受滑鼠事件。當你想子類化或建立你自己的靜態文字控制元件時,它是更可取的。

你可以使用DrawText(text , x,y) 和DrawRotatedText(text , x, y, angle) 方法直接繪製文字到你的裝置上下文。後者是顯示有一定角度的文字的最容易的方法,儘管GenStaticText 的子類也能處理旋轉問題。裝置上下文在第6章中做了簡短的說明,我們將在第12章中對它做更詳細的說明。

如何讓使用者輸入文字?

超越純粹顯示靜態文字,我們將開始討論當輸入文字時的使用者互動。wxPython 的文字域視窗部件的類是wx.TextCtrl ,它允許單行和多行文字輸入。它也可以作為密碼輸入控制元件,掩飾所按下的按鍵。如果平臺支援的話,wx.TextCtrl 也提供豐富格式文字的顯示,通過使用所定義和顯示的多文字樣式。圖7.2顯示了一個作為單行控制元件的wx.TextCtrl 的樣板。其中的密碼輸入框對密碼進行了掩飾。

w7.2.gif

接下來,我們將演示如何建立文字,然後討論文字控制元件的樣式選項。

如何建立文字輸入控制元件

例子7.2顯示了用於生成圖7.2的程式碼

例7.2 wx.TextCtrl 的單行例子

Python程式碼  收藏程式碼
  1. import wx  
  2. class TextFrame(wx.Frame):  
  3.     def __init__(self):  
  4.         wx.Frame.__init__(selfNone, -1'Text Entry Example',   
  5.                 size=(300100))  
  6.         panel = wx.Panel(self, -1)   
  7.         basicLabel = wx.StaticText(panel, -1"Basic Control:")  
  8.         basicText = wx.TextCtrl(panel, -1"I've entered some text!",   
  9.                 size=(175, -1))  
  10.         basicText.SetInsertionPoint(0)  
  11.         pwdLabel = wx.StaticText(panel, -1"Password:")  
  12.         pwdText = wx.TextCtrl(panel, -1"password", size=(175, -1),   
  13.                 style=wx.TE_PASSWORD)  
  14.         sizer = wx.FlexGridSizer(cols=2, hgap=6, vgap=6)  
  15.         sizer.AddMany([basicLabel, basicText, pwdLabel, pwdText])  
  16.         panel.SetSizer(sizer)  
  17. if __name__ == '__main__':  
  18.     app = wx.PySimpleApp()  
  19.     frame = TextFrame()  
  20.     frame.Show()  
  21.     app.MainLoop()  
 

wx.TextCtrl 類的建構函式較小且比其父類wx.Window 更精細,它增加了兩個引數:

wx.TextCtrl(parent , id , value = "", pos =wx.DefaultPosition , size =wx.DefaultSize , style =0, validator=wx.DefaultValidator name =wx.TextCtrlNameStr)

引數parent , id , pos , size , style , 和 name 與wx.Window 建構函式的相同。value 是顯示在該控制元件中的初始文字。

validator 引數用於一個wx.Validator 。validator 通常用於過慮資料以確保只能鍵入要接受的資料。將在第9章對validator 做更詳細的討論。

使用單行文字控制元件樣式

這裡,我們將討論一些唯一無二的文字控制元件樣式。 表7.3說明了用於單行文字控制元件的樣式標記

表7.3 單行wx.TextCtrl 的樣式

wx.TE_CENTER :控制元件中的文字居中。

wx.TE_LEFT :控制元件中的文字左對齊。預設行為。

wx.TE_NOHIDESEL :文字始終高亮顯示,只適用於Windows 。

wx.TE_PASSWORD :不顯示所鍵入的文字,代替以星號顯示。

wx.TE_PROCESS_ENTER :如果使用了這個樣式,那麼當用戶在控制元件內按下回車鍵時,一個文字輸入事件被觸發。否則,按鍵事件內在的由該文字控制元件或該對話方塊管理。

wx.TE_PROCESS_TAB :如果指定了這個樣式,那麼通常的字元事件在Tab 鍵按下時建立(一般意味一個製表符將被插入文字)。否則,tab 由對話方塊來管理,通常是控制元件間的切換。

wx.TE_READONLY :文字控制元件為只讀,使用者不能修改其中的文字。

wx.TE_RIGHT :控制元件中的文字右對齊。

像其它樣式標記一樣,它們可以使用|符號來組合使用,儘管其中的三個對齊標記是相互排斥的。

對於新增文字和移動插入點,該文字控制元件自動管理使用者的按鍵和滑鼠事件。對於該文字控制元件可用的命令控制組合說明如下:

  • ctrl -x :剪下 ctrl -c :複製 ctrl -v :貼上 ctrl -z :撤消

不輸入的情況下如何改變文字?

除了根據使用者的輸入改變顯示的文字外,wx.TextCtrl 提供了在程式中改變顯示的文字的一些方法。你可以完全改變文字或僅移動插入點到文字中不同的位置。表7.4列出了wx.TextCtrl 的文字處理方法。

表7.4

AppendText(text) :在尾部新增文字。

Clear() :重置控制元件中的文字為“”。並且生成一個文字更新事件。

EmulateKeyPress(event) :產生一個按鍵事件,插入與事件相關聯的控制符,就如同實際的按鍵發生了。

GetInsertionPoint() SetInsertionPoint(pos) SetInsertionPointEnd() :得到或設定插入點的位置,位置是整型的索引值。控制元件的開始位置是0。

GetRange(from , to) :返回控制元件中位置索引範圍內的字串。

GetSelection() GetStringSelection() SetSelection(from , to) :GetSelection() 以元組的形式返回當前所選擇的文字的起始位置的索引值(開始,結束)。GetStringSelection() 得到所選擇的字串。SetSelection(from ,to) 設定選擇的文字。

GetValue() SetValue(value) :SetValue() 改變控制元件中的全部文字。GetValue() 返回控制元件中所有的字串。

Remove(from , to) :刪除指定範圍的文字。

Replace(from , to , value) :用給定的值替換掉指定範圍內的文字。這可以改變文字的長度。

WriteText(text) :類似於AppendText() ,只是寫入的文字被放置在當前的插入點。

當你的控制元件是隻讀的或如果你根據事件而非使用者鍵盤輸入來改變控制元件中的文字是,這些方法是十分有用的。

如何建立一個多行或樣式文字控制元件?

你可以使用wx.TE_MULTILINE 樣式標記建立一個多行文字控制元件。如果本地視窗控制元件支援樣式,那麼你可以改變被控制元件管理的文字的字型和顏色樣式,這有時被稱為豐富格式文字。對於另外的一些平臺,設定樣式的呼叫被忽視掉了。圖7.3顯示了多行文字控制元件的一個例子。

w7.3.gif

例7.3包含了用於建立圖7.3的程式碼。通常,建立一個多行文字控制元件是通過設定wx.TE_MULTILINE 樣式標記來處理的。較後的部分,我們將討論使用豐富文字樣式。

例7.3 建立一個多行文字控制元件

Python程式碼  收藏程式碼
  1. import wx  
  2. class TextFrame(wx.Frame):  
  3.     def __init__(self):  
  4.         wx.Frame.__init__(selfNone, -1'Text Entry Example',   
  5.                 size=(300250))  
  6.         panel = wx.Panel(self, -1)   
  7.         multiLabel = wx.StaticText(panel, -1"Multi-line")  
  8.         multiText = wx.TextCtrl(panel, -1,  
  9.                "Here is a looooooooooooooong line of text set in the control.\n\n"  
  10.                "See that it wrapped, and that this line is after a blank",  
  11.                size=(200100), style=wx.TE_MULTILINE) #建立一個文字控制元件  
  12.         multiText.SetInsertionPoint(0#設定插入點  
  13.         richLabel = wx.StaticText(panel, -1"Rich Text")  
  14.         richText = wx.TextCtrl(panel, -1,   
  15.                 "If supported by the native control, this is reversed, and this is a different font.",  
  16.                 size=(200100), style=wx.TE_MULTILINE|wx.TE_RICH2) #建立豐富文字控制元件  
  17.         richText.SetInsertionPoint(0)  
  18.         richText.SetStyle(4452, wx.TextAttr("white""black")) #設定文字樣式  
  19.         points = richText.GetFont().GetPointSize()   
  20.         f = wx.Font(points + 3, wx.ROMAN, wx.ITALIC, wx.BOLD, True#建立一個字型  
  21.         richText.SetStyle(6882, wx.TextAttr("blue", wx.NullColour, f)) #用新字型設定樣式  
  22.         sizer = wx.FlexGridSizer(cols=2, hgap=6, vgap=6)  
  23.         sizer.AddMany([multiLabel, multiText, richLabel, richText])  
  24.         panel.SetSizer(sizer)  
  25. if __name__ == '__main__':  
  26.     app = wx.PySimpleApp()  
  27.     frame = TextFrame()  
  28.     frame.Show()  
  29.     app.MainLoop()  
 

使用多行或豐富文字樣式

除了wx.TE_MULTILINE ,還有另外的樣式標記,它們只在一個多行或豐富文字控制元件的上下文中有意義。表7.5列出了這些視窗樣式。

表7.5

wx.HSCROLL :如果文字控制元件是多行的,並且如果該樣式被聲明瞭,那麼長的行將不會自動換行,並顯示水平滾動條。該選項在GTK +中被忽略。

wx.TE_AUTO_URL :如果豐富文字選項被設定並且平臺支援的話,那麼當用戶的滑鼠位於文字中的一個URL 上或在該URL 上敲擊時,這個樣式將導致一個事件被生成。

wx.TE_DONTWRAP :wx.HSCROLL 的別名。

wx.TE_LINEWRAP :對於太長的行,以字元為界換行。某些作業系統可能會忽略該樣式。

wx.TE_MULTILINE :文字控制元件將顯示多行。

wx.TE_RICH :用於Windows 下,豐富文字控制元件用作基本的視窗部件。這允許樣式文字的使用。

wx.TE_RICH2 :用於Windows 下,把最新版本的豐富文字控制元件用作基本的視窗部件。

wx.TE_WORDWRAP :對於太長的行,以單詞為界換行。許多作業系統會忽略該樣式。

記住,上面這些樣式可以組合使用,所以上面例子中的多行豐富文字控制元件使用wx.TE_MULTILINE | wx.TE_RICH2 來宣告。

用在wx.TextCtrl 視窗部件中的文字樣式是類wx.TextAttr 的例項。wx.TextAttr 例項的屬性有文字顏色、背景色、和字型,它們都能夠在建構函式中被指定,如下所示:

wx.TextAttr(colText , colBack =wx.NullColor , font =wx.NullFont)

文字色和背景色是wxPython 物件,它們可以使用顏色名或顏色的RGB 值(紅, 綠, 藍)來指定。wx.NullColor 指明使用控制元件目前的背景色。font 是一個wx.Font 物件,我們將在下一小節討論。wx.NullFont 物件指明使用當前預設字型。

wx.TextAttr 有相關屬性的get *()方法:GetBackgroundColour() , GetFont() , 和 GetTextColour() ,也有返回布林值的驗證存在性的方法:HasBackgroundColour() , HasFont() , 和 HasTextColour() 。如果屬性包含一個預設值,則Has *()方法返回False 。如果所有這三個屬性都包含預設值,則IsDefault() 方法返回true 。這個類沒有set *()方法,因為wx.TextAttr 的例項是不可變的。要改變文字的樣式,你必須建立一個例項。

使用文字樣式,要呼叫SetDefaultStyle(style) 或SetStyle(start , end ,style) 。第一個方法設定為控制元件當前的樣式。任何插入到該控制元件中的文字,不管是鍵入的,或使用了AppendText() 或 WriteText() 方法的,都以該樣式顯示。如果樣式的某個屬性是預設的,那麼該樣式的當前值被保留。但是,如果樣式的所有屬性都是預設的,那麼恢復預設樣式。

SetStyle() 與SetDefaultStyle(style) 類似,只是立即對位於start 和 end 位置之間的文字起作用。樣式引數中的預設屬性通過檢查該控制元件的當前預設樣式來解決。例7.3使用下面一行程式碼來反轉文字中幾個字元的顏色:

richText.SetStyle(44 , 52, wx.TextAttr( "white ", "black "))

背景色變為了黑色,相應的字元變為了白色。

表7.6列出了wx.TextCtrl 的方法,它們在處理多行控制元件和豐富文字中是有用的。

表7.6

GetDefaultStyle() SetDefaultStyle(style) :上面已作了說明。

GetLineLength(lineNo) :返回給定行的長度的整數值。

GetLineText(lineNo) :返回給定行的文字。

GetNumberOfLines() :返回控制元件中的行的數量。對於單行,返回1。

IsMultiLine() IsSingleLine() :布林型別的方法,確定控制元件的狀態。

PositionToXY(pos) :指定文字內的一個整數值位置,返回以元組(列,行)形式的索引位置。列和行的索引值均以0作為開始。

SetStyle(start , end ,style) :立即改變指定範圍內文字的樣式。

ShowPosition(pos) :引起一個多行控制元件的滾動,以便觀察到指定位置的內容。

XYToPosition(x , y) :與PositionToXY(pos) 相反——指定行和列,返回整數值位置。

如果你能在系統中使用任意字型的話,那麼就可以更加靈活的建立樣式。 接下來,我們將給你展示如何建立和使用字型例項。

如何建立一個字型?

字型是類wx.Font 的例項。你所訪問的任何字型,它已經被安裝並對於基本的系統是可訪問的。建立一個字型例項,要使用如下的建構函式:

Python程式碼  收藏程式碼
  1. wx.Font(pointSize, family, style, weight, underline=False, faceName="", encoding=wx.FONTENCODING_DEFAULT)  
 

pointSize 是字型的以磅為單位的整數尺寸。family 用於快速指定一個字型而無需知道該字型的實際的名字。字型的準確選擇依賴於系統和具體可用的字型。可用的字型類別的示例顯示在表7.7中。你所得到的精確的字型將依賴於你的系統。

表7.7

wx.DECORATIVE :一個正式的,老的英文樣式字型。

wx.DEFAULT :系統預設字型。

wx.MODERN :一個單間隔(固定字元間距)字型。

wx.ROMAN :serif 字型,通常類似於Times New Roman 。

wx.SCRIPT :手寫體或草寫體

wx.SWISS :sans -serif 字型,通常類似於Helvetica 或Arial 。

style 引數指明字型的是否傾斜,它的值有:wx.NORMAL , wx.SLANT , 和 wx.ITALIC 。同樣,weight 引數指明字型的醒目程度,可選值有:wx.NORMAL , wx.LIGHT ,或wx.BOLD 。這些常量值的行為根據它的名字就可以知道了。underline 引數僅工作在Windows 系統下,如果取值為True ,則加下劃線,False 為無下劃線。 faceName 引數指定字型名。

encoding 引數允許你在幾個編碼中選擇一個,它對映內部的字元和字本顯示字元。編碼不是Unicode 編碼,只是用於wxPython 的不同的8位編碼。大多數情況你可以使用預設編碼。

為了獲取系統的有效字型的一個列表,並使使用者可用它們,要使用專門的類wx.FontEnumerator ,如下所示:

e = wx.FontEnumerator() e.EnumerateFacenames() fontList = e.GetFacenames()

要限制該列表為固定寬度,就要將上面的第一行改為e = wx.FontEnumerator(fixedWidth =True) 。

如果我們系統不支援豐富文字,那麼我還能使用樣式文字嗎?

可以。在wxPython 中有一個跨平臺的樣式文字視窗部件,名為wx.stc.StyledTextCtrl ,它是Python 對Scintilla豐富文字元件的封裝。因為Scintilla 不是wxWidgets 的一部分,而是作為一個獨立的第三方組被合併到了wxPython 中,所以它不與我們已經討論過的類共享相同的API 。wx.stc.StyledCtrl 的完整說明超過了我們要講的範圍,但是你可以在http: //wiki.wxpython.org /index.cgi /wxStyledTextCtrl 找到相關的文件。

如果我的文字控制元件不匹配我的字串該怎麼辦?

當使用多行wx.TextCtrl 的時候,要知道的一點是,該文字控制元件是以何種方式儲存字串的。在內部,儲存在該wx.TextCtrl 中的多行字元是以\n作為行的分隔符的。這與基本的作業系統無關,即使某些系統使用了不同的字元組合作為一行的分隔符。當你使用GetValue() 來獲取該字串時,原來的行分隔符被還原,因此你不必考慮手工轉換。這個的好處就是控制元件中的文字不依賴於任何特定的作業系統。

缺點是,文字控制元件中的行的長度和行的索引與它們在文字控制元件外的可能是不同的。例如,如果你在一個Windows 系統上,系統所用的行分隔符是\r\n,通過GetValue() 所得知的字串的長度將比通過GetLastPosition() 所得知的字串的結尾長。通過在例7.3中增加下面兩行:

print "getValue ", len(multiText.GetValue()) print "lastPos ", multiText.GetLastPosition()

我們在Unix 系統上所得的結果應該是:

getValue 119 lastPos 119

我們在Windows 系統上所得的結果應該是:

getValue 121 lastPos 119

這意味你不應該使用多行文字控制元件的位置索引來取得原字串,位置索引應該用作wx.TextCtrl 的另外方法的引數。對於該控制元件中的文字的子串,應該使用GetRange() 或GetSelectedText() 。也不要反向索引;不要使用原字串的索引來取得並放入文字控制元件中。下面是一個例子,它使用了不正確的方法在插入點之後直接得到10個字元:

Python程式碼  收藏程式碼
  1. aLongString = """Any old 
  2. multi line string 
  3. will do here. 
  4. Just as long as 
  5. it is multiline"""  
  6. text = wx.TextCtrl(panel, -1, aLongString, style=wx.TE_MULTILINE)  
  7. x = text.GetInsertionPoint()  
  8. selection = aLongString[x : x + 10### 這將是不正確的  
 

Windows 或Mac 系統中要得到正確的結果,最後一行應換為:

selection = text.GetRange(x , x + 10)

如何響應文字事件?

有一個由wx.TextCtrl 視窗部件產生的便利的命令事件,你可能想用它。你需要把相關事件傳遞給Bind 方法以捕獲該事件,如下所示:

frame.Bind(wx.EVT_TEXT , frame.OnText , text)

表7.8說明了這些命令事件。

表7.8 wx.TextCtrl 的事件

EVT_TEXT :當控制元件中的文字改變時產生該事