《零基礎入門學習Python》(35)--圖形使用者介面入門:EasyGui
0. 安裝 EasyGUI
進行下載,下載好了儘量將它放在你python安裝目錄下面,方面查詢
使用 pip 進行安裝:
1. 什麼是 EasyGUI?
EasyGUI 是 Python 中一個非常簡單的 GUI 程式設計模組,不同於其他的 GUI 生成器,它不是事件驅動的。相反,所有的 GUI 互動都是通過簡地函式呼叫就可以實現。
EasyGUI 為使用者提供了簡單的 GUI 互動介面,不需要程式設計師知道任何有關 tkinter,框架,部件,回撥或 lambda 的任何細節。
EasyGUI 可以很好地相容 Python 2 和 3,並且不存在任何依賴關係。
EasyGUI 是執行在 Tkinter 上並擁有自身的事件迴圈,而 IDLE 也是 Tkinter 寫的一個應用程式並也擁有自身的事件迴圈。因此當兩者同時執行的時候,有可能會發生衝突,且帶來不可預測的結果。因此如果你發現你的 EasyGUI 程式有這樣的問題,請嘗試在 IDLE 外去執行你的程式。
2. 一個簡單的例子
在 EasyGui 中,所有的 GUI 互動均是通過簡單的函式呼叫,下邊一個簡單的例子告訴你 EasyGui 確實很 Easy!
import easygui as g import sys while 1: g.msgbox("嗨,歡迎進入第一個介面小遊戲^_^") msg ="請問你希望在魚C工作室學習到什麼知識呢?" title = "小遊戲互動" choices = ["談戀愛", "程式設計", "OOXX", "琴棋書畫"] choice = g.choicebox(msg, title, choices) # 注意,msgbox的引數是一個字串 # 如果使用者選擇Cancel,該函式返回None g.msgbox("你的選擇是: " + str(choice), "結果") msg = "你希望重新開始小遊戲嗎?" title = "請選擇" # 彈出一個Continue/Cancel對話方塊 if g.ccbox(msg, title): pass # 如果使用者選擇Continue else: sys.exit(0) # 如果使用者選擇Cancel
3. EasyGUI 的各種功能演示
要執行 EasyGUI 的演示程式,在命令列呼叫 EasyGUI 是這樣的:
python easygui.py
或者可以從 IDE(例如 IDLE, PythonWin, Wing, 等等)上呼叫:
>>> import easygui
>>> easygui.egdemo()
成功呼叫後將可以嘗試 EasyGUI 擁有的各種功能,並將結果列印至控制檯
4. 匯入 EasyGUI
為了使用 EasyGUI 這個模組,你應該先匯入它。
最簡單的匯入語句是:
import easygui
如果使用上面這種形式匯入的話,那麼你使用 EasyGUI 的函式的時候,必須在函式的前面加上字首 easygui,像這樣:
easygui.msgbox(...)
另一種選擇是匯入整個 EasyGUI 包:
from easygui import *
這使得我們更容易呼叫 EasyGUI 的函式,可以直接這樣編寫程式碼:
msgbox(...)
第三種方案是使用類似下邊的 import 語句:
import easygui as g
這種方法還可以讓你保持 EasyGUI 的名稱空間,同時減少你的打字數量。
匯入之後就可以這麼呼叫 EasyGUI 的函式:
g.msgbox(...)
5. 使用 EasyGUI
一旦你的模組匯入 EasyGUI,GUI 操作就是一個簡單的呼叫 EasyGUI 函式的幾個引數的問題了。
例如,使用 EasyGUI 來實現世界上最著名的打招呼:
import easygui as g
g.msgbox("Hello, world!")
6. EasyGUI 函式的預設引數
對於所有對話方塊而言,前兩個引數都是訊息主體和對話方塊標題。
按照這個規律,在某種情況下,這可能不是理想的佈局設計(比如當對話方塊在獲取目錄或檔名的時候會選擇忽略訊息引數),但保持這種一致性且貫穿於所有的視窗部件是更為得體的考慮!
絕大部分的 EasyGUI 函式都有預設引數,幾乎所有的元件都會顯示訊息主體和對話方塊標題。
標題預設是空字串,訊息主體通常有一個簡單的預設值。
這使得你可以儘可能少的去設定引數,比如 msgbox() 函式標題部分的引數是可選的,因此你呼叫 msgbox() 的時候只需要指定一個訊息引數即可,例如:
>>> g.msgbox('hello world!!!!')
當然你也可以指定標題引數和訊息引數,例如:
>>> g.msgbox('hello world','go go go')
在各類按鈕元件裡,預設的訊息是 “Shall I continue?”,所以你可以不帶任何引數地去呼叫它們。
這裡我們演示不帶任何引數地去呼叫 ccbox(),當選擇 “cancel” 或關閉視窗的時候返回一個布林型別的值:
import easygui as g
while True:
if g.ccbox():
pass # user chose to continue
else:
exit() # user chose to cancel
7. 使用關鍵字引數呼叫EasyGui函式
呼叫EasyGui函式還可以使用關鍵字引數
現在假設你需要使用一個按鈕元件,但你不想指定標題引數
(第二個引數),你仍可以使用關鍵字引數的方法指定choices
引數(第三個引數),像這樣:
import easygui as g
xz = ['棒','真棒','超級棒']
replay = g.choicebox('我棒不棒?',choices=xz)
8. 使用按鈕組建
根據需求,EasyGui在buttonbox()上建立了一系列的函式供呼叫。
8.1 msgbox()
>>> help(g.msgbox)
Help on function msgbox in module easygui.boxes.derived_boxes:
msgbox(msg='(Your message goes here)', title=' ', ok_button='OK', image=None, root=None)
Display a message box
:param str msg: the msg to be displayed
:param str title: the window title
:param str ok_button: text to show in the button
:param str image: Filename of image to display
:param tk_widget root: Top-level Tk widget
:return: the text of the ok_button
重寫OK
按鈕最簡單的方法是使用關鍵字引數:
import easygui as g
g.msgbox('我一定要學會Python', ok_button='加油')
8.2 ccbox()
>>> help(g.ccbox)
Help on function ccbox in module easygui.boxes.derived_boxes:
ccbox(msg='Shall I continue?', title=' ', choices=('C[o]ntinue', 'C[a]ncel'), image=None, default_choice='Continue', cancel_choice='Cancel')
Display a msgbox with choices of Continue and Cancel.
The returned value is calculated this way::
if the first choice ("Continue") is chosen,
or if the dialog is cancelled:
return True
else:
return False
If invoked without a msg argument, displays a generic
request for a confirmation
that the user wishes to continue. So it can be used this way::
if ccbox():
pass # continue
else:
sys.exit(0) # exit the program
:param str msg: the msg to be displayed
:param str title: the window title
:param list choices: a list or tuple of the choices to be displayed
:param str image: Filename of image to display
:param str default_choice: The choice you want highlighted
when the gui appears
:param str cancel_choice: If the user presses the 'X' close,
which button should be pressed
:return: True if 'Continue' or dialog is cancelled, False if 'Cancel'
ccbox()
提供一個選擇:Continue
或者Cancel
,並相應的返回1(選中Continue)或者0(選中Cancel)。
【注意】:ccbox()是返回整形的1或0,不是布林型別的True或False。但你仍然可以這麼些:
import sys
import easygui as g
if g.ccbox('要再來一次嗎?',choices=('要啊要啊^_^', '算了吧T_T')):
g.msgbox('不給玩了,再玩就玩壞了……')
else:
sys.exit(0)
8.3 ynbox()
>>> help(g.ynbox)
Help on function ynbox in module easygui.boxes.derived_boxes:
ynbox(msg='Shall I continue?', title=' ', choices=('[<F1>]Yes', '[<F2>]No'), image=None, default_choice='[<F1>]Yes', cancel_choice='[<F2>]No')
Display a msgbox with choices of Yes and No.
The returned value is calculated this way::
if the first choice ("Yes") is chosen, or if the dialog is cancelled:
return True
else:
return False
If invoked without a msg argument, displays a generic
request for a confirmation
that the user wishes to continue. So it can be used this way::
if ynbox():
pass # continue
else:
sys.exit(0) # exit the program
:param msg: the msg to be displayed
:type msg: str
:param str title: the window title
:param list choices: a list or tuple of the choices to be displayed
:param str image: Filename of image to display
:param str default_choice: The choice you want highlighted
when the gui appears
:param str cancel_choice: If the user presses the 'X' close, which
button should be pressed
:return: True if 'Yes' or dialog is cancelled, False if 'No'
同8.2
8.4 buttonbox()
>>> help(g.buttonbox)
Help on function buttonbox in module easygui.boxes.button_box:
buttonbox(msg='', title=' ', choices=('Button[1]', 'Button[2]', 'Button[3]'), image=None, images=None, default_choice=None, cancel_choice=None, callback=None, run=True)
Display a msg, a title, an image, and a set of buttons.
The buttons are defined by the members of the choices global_state.
:param str msg: the msg to be displayed
:param str title: the window title
:param list choices: a list or tuple of the choices to be displayed
:param str image: (Only here for backward compatibility)
:param str images: Filename of image or iterable or iteratable of iterable to display
:param str default_choice: The choice you want highlighted when the gui appears
:return: the text of the button that the user selected
可以使用buttonbox()定義自己的一組按鈕,buttonbox()會顯示一組你定義好的按鈕。
當用戶點選任意一個按鈕的時候,buttonbox()返回按鈕的文字內容。如果使用者取消或者關閉視窗,那麼會返回預設選項(第一個選項)。請看示例:
import easygui as g
g.buttonbox(choices=('草莓','西瓜','芒果','巧克力'))
8.5 indexbox()
>>> help(g.indexbox)
Help on function indexbox in module easygui.boxes.derived_boxes:
indexbox(msg='Shall I continue?', title=' ', choices=('Yes', 'No'), image=None, default_choice='Yes', cancel_choice='No')
Display a buttonbox with the specified choices.
:param str msg: the msg to be displayed
:param str title: the window title
:param list choices: a list or tuple of the choices to be displayed
:param str image: Filename of image to display
:param str default_choice: The choice you want highlighted
when the gui appears
:param str cancel_choice: If the user presses the 'X' close,
which button should be pressed
:return: the index of the choice selected, starting from 0
基本上跟上邊一樣,區別就是當用戶選擇第一個按鈕的時候返回序號0,選擇第二個按鈕的時候返回序號1
8.6 boolbox()
>>> help(g.boolbox)
Help on function boolbox in module easygui.boxes.derived_boxes:
boolbox(msg='Shall I continue?', title=' ', choices=('[Y]es', '[N]o'), image=None, default_choice='Yes', cancel_choice='No')
Display a boolean msgbox.
The returned value is calculated this way::
if the first choice is chosen, or if the dialog is cancelled:
returns True
else:
returns False
:param str msg: the msg to be displayed
:param str title: the window title
:param list choices: a list or tuple of the choices to be displayed
:param str image: Filename of image to display
:param str default_choice: The choice you want highlighted
when the gui appears
:param str cancel_choice: If the user presses the 'X' close, which button
should be pressed
:return: True if first button pressed or dialog is cancelled, False if
second button is pressed
如果第一個按鈕被選中返回1,否則返回0.
9. 如何在buttonbox裡顯示圖片
當你呼叫一個buttonbox函式(例如:msgbox(),ynbox(),indexbox()等)的時候,你還可以為關鍵字引數image賦值,這是設定一個.gif
格式的影象(注意僅支援GIF格式)
import easygui as g
g.buttonbox('大家說我長得帥嗎?', image='1.gif', choices=('帥', '不帥', '你大爺'))
10. 為使用者提供一系列選項
10.1 choicebox()
>>> help(g.choicebox)
Help on function choicebox in module easygui.boxes.choice_box:
choicebox(msg='Pick an item', title='', choices=[], preselect=0, callback=None, run=True)
Present the user with a list of choices.
return the choice that he selects.
:param str msg: the msg to be displayed
:param str title: the window title
:param list choices: a list or tuple of the choices to be displayed
:param preselect: Which item, if any are preselected when dialog appears
:return: List containing choice selected or None if cancelled
按鈕組建方便提供使用者一個簡單的按鈕選項,但如果有很多選項,或者選項的內容特別長的話,更好的策略是為它們提供一個可選擇的列表。
choicebox()為使用者提供了一個可選擇的列表,使用序列(元祖或列表)作為選項,這些選項顯示前會按照不區分大小寫的方法排好序。
另外還可以使用鍵盤來選擇其中一個選項(比較糾結,但一點兒都不重要):
- 例如當按下鍵盤上g鍵,將會選中第一個以g開頭的選項。再次按下g鍵,則會選中下一個以g開頭的選項。在選中最後一個以g開頭的選項時候,再次按下g鍵將重新回到在列表的開頭的第一個以g開頭的選項。
- 如果選項中沒有以g開頭的,則會選中字元排序在g之前f的那個字元開頭的選項
- 如果選項中沒有字元排序在g之前,那麼在列表中第一個元素將會被選中。
綜合我們之前的學習檔案功能,舉個例子:
import easygui as g
target = ['.mp4','.avi','.rmvb','.mkv','.torrent']
vedio_list = []
import os
def serach_file(start_dir,target):
os.chdir(start_dir)
for each_file in os.listdir(os.curdir):
ext = os.path.splitext(each_file)[1]
if ext in target:
vedio_list.append(os.getcwd() + os.sep +each_file + os.linesep)
if os.path.isdir(each_file):
serach_file(each_file,target)
os.chdir(os.pardir)
start_dir = input('請輸入需要查詢的目錄:')
program_dir = os.getcwd()
serach_file(start_dir,target)
f = open(program_dir + os.sep + 'vedioList.txt','w')
f.writelines(vedio_list)
f.close()
g.choicebox(msg='在 【%s】 系列路徑下工搜尋滿足條件的檔案如下' % start_dir,choices=vedio_list)
12. 讓使用者輸入密碼
有時候我們需要讓使用者輸入密碼,就是使用者輸入的東西看上去都是**********
12.1 passwordbox()
>>> help(g.passwordbox)
Help on function passwordbox in module easygui.boxes.derived_boxes:
passwordbox(msg='Enter your password.', title=' ', default='', image=None, root=None)
Show a box in which a user can enter a password.
The text is masked with asterisks, so the password is not displayed.
:param str msg: the msg to be displayed.
:param str title: the window title
:param str default: value returned if user does not change it
:return: the text that the user entered, or None if he cancels
the operation.
passwordbox()跟enterbox()樣式一樣,不同的是使用者輸入的內容用*
顯示,返回使用者輸入的字串:
12.2 multpasswordbox()
>>> help(g.multpasswordbox)
Help on function multpasswordbox in module easygui.boxes.multi_fillable_box:
multpasswordbox(msg='Fill in values for the fields.', title=' ', fields=(), values=(), callback=None, run=True)
Same interface as multenterbox. But in multpassword box,
the last of the fields is assumed to be a password, and
is masked with asterisks.
:param str msg: the msg to be displayed.
:param str title: the window title
:param list fields: a list of fieldnames.
:param list values: a list of field values
:return: String
**Example**
Here is some example code, that shows how values returned from
multpasswordbox can be checked for validity before they are accepted::
msg = "Enter logon information"
title = "Demo of multpasswordbox"
fieldNames = ["Server ID", "User ID", "Password"]
fieldValues = [] # we start with blanks for the values
fieldValues = multpasswordbox(msg,title, fieldNames)
# make sure that none of the fields was left blank
while 1:
if fieldValues is None: break
errmsg = ""
for i in range(len(fieldNames)):
if fieldValues[i].strip() == "":
errmsg = errmsg + ('"%s" is a required field.\n\n' %
fieldNames[i])
if errmsg == "": break # no problems found
fieldValues = multpasswordbox(errmsg, title,
fieldNames, fieldValues)
print("Reply was: %s" % str(fieldValues))
multpasswordbox()跟multenterbox()使用相同的介面,但當它顯示的時候,最後一個輸入框顯示為密碼的形式*
from easygui import *
msg = "驗證登陸資訊"
title = "密碼函式multpasswordbox示例"
fieldNames = ["伺服器 ID", "使用者 ID", "密碼"]
fieldValues = [] # we start with blanks for the values
fieldValues = multpasswordbox(msg, title, fieldNames)
print("輸入的資訊是: %s" % str(fieldValues))
13. 顯示文字
EasyGui還提供函式用於顯示文字。
13.1 textbox()
>>> help(g.textbox)
Help on function textbox in module easygui.boxes.text_box:
textbox(msg='', title=' ', text='', codebox=False, callback=None, run=True)
Display a message and a text to edit
Parameters
----------
msg : string
text displayed in the message area (instructions...)
title : str
the window title
text: str, list or tuple
text displayed in textAreas (editable)
codebox: bool
if True, don't wrap and width is set to 80 chars
callback: function
if set, this function will be called when OK is pressed
run: bool
if True, a box object will be created and returned, but not run
Returns
-------
None
If cancel is pressed
str
If OK is pressed returns the contents of textArea
textbox()函式預設會以比例字型(引數codebox = 1設定為等寬字型)來顯示文字內容(會自動換行哦),這個函式適合用於顯示一般的書面文字。
【注意】:text引數(第三個引數)可以是字串,列表或者元祖型別。
13.2 codebox()
>>> help(g.codebox)
Help on function codebox in module easygui.boxes.derived_boxes:
codebox(msg='', title=' ', text='')
Display some text in a monospaced font, with no line wrapping.
This function is suitable for displaying code and text that is
formatted using spaces.
The text parameter should be a string, or a list or tuple of lines to be
displayed in the textbox.
:param str msg: the msg to be displayed
:param str title: the window title
:param str text: what to display in the textbox
codebox()以等寬字型顯示文字內容,相當於testbox(codebox = 1)
14. 目錄與檔案
GUI程式設計中一個常見的場景是要求使用者輸入目錄及檔名,EasyGui提供了一些基本函式讓使用者來瀏覽檔案系統,選擇一個目錄或檔案。
14.1 diropenbox()
>>> help(g.diropenbox)
Help on function diropenbox in module easygui.boxes.diropen_box:
diropenbox(msg=None, title=None, default=None)
A dialog to get a directory name.
Note that the msg argument, if specified, is ignored.
Returns the name of a directory, or None if user chose to cancel.
If the "default" argument specifies a directory name, and that
directory exists, then the dialog box will start with that directory.
:param str msg: the msg to be displayed
:param str title: the window title
:param str default: starting directory when dialog opens
:return: Normalized path selected by user
diropenbox()函式用於提供一個對話方塊,返回使用者選擇的目錄名(帶完整路徑),如果使用者選擇Cancel
則返回None。
default引數用於設定預設的開啟目錄(請確保設定的目錄已存在。)
>>> g.diropenbox()
14.2 fileopenbox()
>>> help(g.fileopenbox)
Help on function fileopenbox in module easygui.boxes.fileopen_box:
fileopenbox(msg=None, title=None, default='*', filetypes=None, multiple=False)
A dialog to get a file name.
**About the "default" argument**
The "default" argument specifies a filepath that (normally)
contains one or more wildcards.
fileopenbox will display only files that match the default filepath.
If omitted, defaults to "\*" (all files in the current directory).
WINDOWS EXAMPLE::
...default="c:/myjunk/*.py"
will open in directory c:\myjunk\ and show all Python files.
WINDOWS EXAMPLE::
...default="c:/myjunk/test*.py"
will open in directory c:\myjunk\ and show all Python files
whose names begin with "test".
Note that on Windows, fileopenbox automatically changes the path
separator to the Windows path separator (backslash).
**About the "filetypes" argument**
If specified, it should contain a list of items,
where each item is either:
- a string containing a filemask # e.g. "\*.txt"
- a list of strings, where all of the strings except the last one
are filemasks (each beginning with "\*.",
such as "\*.txt" for text files, "\*.py" for Python files, etc.).
and the last string contains a filetype description
EXAMPLE::
filetypes = ["*.css", ["*.htm", "*.html", "HTML files"] ]
.. note:: If the filetypes list does not contain ("All files","*"), it will be added.
If the filetypes list does not contain a filemask that includes
the extension of the "default" argument, it will be added.
For example, if default="\*abc.py"
and no filetypes argument was specified, then
"\*.py" will automatically be added to the filetypes argument.
:param str msg: the msg to be displayed.
:param str title: the window title
:param str default: filepath with wildcards
:param object filetypes: filemasks that a user can choose, e.g. "\*.txt"
:param bool multiple: If true, more than one file can be selected
:return: the name of a file, or None if user chose to cancel
fileopenbox()函式用於提供一個對話方塊,返回使用者選擇的檔名(帶完整路徑),如果使用者選擇Cancel則返回None
關於default引數的設定方法: - default引數指定一個預設路徑,通常包含一個或多個萬用字元。 - 如果設定了default引數,fileopenbox()顯示預設的檔案路徑和格式。 - default預設的引數是*,即匹配所有格式的檔案。
例如: 1. default = ‘c:/fishc/*.py’即顯示c:\fishc資料夾下所有的Python檔案 2. default = ‘c:/fishc/test*.py’即顯示c:\fishc資料夾下所有的名字以test開頭的Python檔案
關於filetypes引數的設定方法: - 可以是包含檔案掩碼的字串列表。例如:filetypes = ['*.txt'] - 可以是字串列表,列表的最後一項字串是檔案型別的描述,例如:filetypes = ['*.css',['*.htm','*.html','*.HTML files']]
>>> g.fileopenbox(default = 'E:\software\*.exe')
'E:\\software\\pycharm-professional-2018.1.1.exe'
>>> g.fileopenbox(filetypes = ['*.py',['*.py','*.python file']])
'D:\\untitled\\Python_learn\\將一個數分解成列表.py'
事例3:
提供一個資料夾瀏覽框,讓使用者選擇需要開啟的檔案,開啟並顯示檔案內容:
import easygui as g
import os
file_path = g.fileopenbox(default="*.txt")
with open(file_path) as f:
title = os.path.basename(file_path)
msg = "檔案【%s】的內容如下:" % title
text = f.read()
g.textbox(msg, title, text)
14.3 filesavebox()
>>> help(g.filesavebox)
Help on function filesavebox in module easygui.boxes.filesave_box:
filesavebox(msg=None, title=None, default='', filetypes=None)
A file to get the name of a file to save.
Returns the name of a file, or None if user chose to cancel.
The "default" argument should contain a filename (i.e. the
current name of the file to be saved). It may also be empty,
or contain a filemask that includes wildcards.
The "filetypes" argument works like the "filetypes" argument to
fileopenbox.
:param str msg: the msg to be displayed.
:param str title: the window title
:param str default: default filename to return
:param object filetypes: filemasks that a user can choose, e.g. " \*.txt"
:return: the name of a file, or None if user chose to cancel
filesavebox()函式提供一個對話方塊,讓用於選擇的檔案需要儲存的路徑(帶完整路勁),如果使用者選擇Cancel則返回None。
default引數應該包含一個檔名(例如當前需要儲存的檔名),當然你也可以設定為空的,或者包含一個檔案格式掩碼的萬用字元
filetypes引數類似於fileopenbox()函式的filetypes引數。
>>> g.filesavebox(default='test.txt')
事例4
在事例3的基礎上增強功能:當用戶點選OK
按鈕的時候,比較當前檔案是否修改過,如果修改過,則提示覆蓋儲存
,放棄儲存
或另存為...
並實現相應功能。
(提示:解決這道題可能需要點耐心,因為你有可能被一個小問題卡住,但請堅持,自己想辦法找到這個小問題並解決它!)
import easygui as g
import os
file_path = g.fileopenbox(default='*.txt')
with open(file_path) as old_file:
title = os.path.basename(file_path)
msg = '檔案【%s】的內容如下:' % title
text = old_file.read()
text_after = g.textbox(msg,title,text)
if text != text_after[:-1]: #textbox的返回值會在末尾追加一個換行符
#buttonbox(msg='', title=' ', choices=('Button1', 'Button2', 'Button3'), image=None, root=None)
choice = g.buttonbox('檢測到檔案內容發生改變,請選擇以下操作:','警告',('覆蓋保持','放棄儲存','另存為...'))
if choice == '覆蓋儲存':
with open(file_path,'w') as old_file:
old_file.write(text_after[:-1])
if choice == '放棄儲存':
pass
if choice == '另存為...':
another_path = g.filesavebox(default='.txt')
if os.path.splitext(another_path)[1] != '.txt':
another_path += '.txt'
with open(another_path,'w') as new_file:
new_file.write(text_after[:-1])
15. 記住使用者的設定
15.1 EgStore
>>> help(g.EgStore)
Help on class EgStore in module easygui.boxes.egstore:
class EgStore(builtins.object)
| EgStore(filename)
|
| A class to support persistent storage.
|
| You can use ``EgStore`` to support the storage and retrieval
| of user settings for an EasyGui application.
|
| **First: define a class named Settings as a subclass of EgStore** ::
|
| class Settings(EgStore):
| def __init__(self, filename): # filename is required
| # specify default values for variables that this application wants to remember
| self.user_id = ''
| self.target_server = ''
| settings.restore()
| *Second: create a persistent Settings object** ::
|
| settings = Settings('app_settings.txt')
| settings.user_id = 'obama_barak'
| settings.targetServer = 'whitehouse1'
| settings.store()
|
| # run code that gets a new value for user_id, and persist the settings
| settings.user_id = 'biden_joe'
| settings.store()
|
| **Example C: recover the Settings instance, change an attribute, and store it again.** ::
|
| settings = Settings('app_settings.txt')
| settings.restore()
| print settings
| settings.user_id = 'vanrossum_g'
| settings.store()
|
| Methods defined here:
|
| __getstate__(self)
| All attributes will be pickled
|
| __init__(self, filename)
| Initialize a store with the given filename.
|
| :param filename: the file that backs this store for saving and loading
|
| __repr__(self)
| Return repr(self).
|
| __setstate__(self, state)
| Ensure filename won't be unpickled
|
| __str__(self)
| "Format this store as "key : value" pairs, one per line.
|
| kill(self)
| Delete this store's file if it exists.
|
| restore(self)
|
| store(self)
| Save this store to a pickle file.
| All directories in :attr:`filename` must already exist.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
GUI程式設計中一個常見的場景就是要求使用者設定一下引數,然後儲存下來,以便下次使用者使用你的程式的時候可以記住他的設定。
為了實現對使用者的設定進行儲存和恢復這一過程,EasyGui提供了一個EgStore的類。為了記住某些設定,你的應用程式必須定義一個類(暫時稱之為“設定”類,儘管你隨意的使用你想要的名稱設定它)繼承自EgStore類。
然後你的應用程式必須建立一個該類的物件(暫時稱之為“設定”物件)
設定類的建構函式(__init__方法)必須初始化所有的你想要它記住的那些值。
一旦你這樣做了,你就可以在“設定”物件中通過設定值去例項化變數,從而簡單地記住設定。之後使用setting.store()方法在硬碟上持久化設定物件。 下面是建立一個“設定”類的例子:
#-----------------------------------------------------------------------
# create "settings", a persistent Settings object
# Note that the "filename" argument is required.
# The directory for the persistent file must already exist.
#-----------------------------------------------------------------------
settingsFilename = os.path.join("C:", "FishCApp", "settings.txt") # Windows example
settings = Settings(settingsFilename)
下面是使用“設定”物件的例子:
# we initialize the "user" and "server" variables
# In a real application, we'd probably have the user enter them via enterbox
user = "奧巴馬"
server = "白宮"
# we save the variables as attributes of the "settings" object
settings.userId = user
settings.targetServer = server
settings.store() # persist the settings
# run code that gets a new value for userId
# then persist the settings with the new value
user = "小甲魚"
settings.userId = user
settings.store()
16. 捕獲異常
- exceptionbox()
>>> help(g.exceptionbox)
Help on function exceptionbox in module easygui.boxes.derived_boxes:
exceptionbox(msg=None, title=None)
Display a box that gives information about
an exception that has just been raised.
The caller may optionally pass in a title for the window, or a
msg to accompany the error information.
Note that you do not need to (and cannot) pass an exception object
as an argument. The latest exception will automatically be used.
:param str msg: the msg to be displayed
:param str title: the window title
:return: None
使用EasyGui編寫GUI程式,有時候難免會產生異常。當然這取決於你如何執行你的應用程式,當你的應用程式崩潰的時候,堆疊追蹤可能會被丟擲,或者被寫入到stdout標準輸出函式中。
EasyGui通過exceptionbox()函式提供了更好的方式去處理異常,異常出現的時候,exceptionbox()會顯示堆疊追蹤在一個codebox()中並且允許你做進一步的處理。
exceptionbox()很容易使用,請看下例:
import easygui as g
try:
print('i love fishc.com')
int('FishC') #這裡會產生異常
except:
g.exceptionbox()
事例5:
寫一個程式統計你當前程式碼量的總和,並顯示離十萬行程式碼量還有多遠?
- 要求1:遞迴搜尋各個資料夾
- 要求2:顯示各個型別的原始檔和原始碼數量
- 要求3:顯示總行數與百分比
截圖1:
截圖2:
import easygui as g
import os
def show_result(start_dir):
lines = 0
total = 0
text = ""
for i in source_list:
lines = source_list[i]
total += lines
text += "【%s】原始檔 %d 個,原始碼 %d 行\n" % (i, file_list[i], lines)
title = '統計結果'
msg = '您目前共累積編寫了 %d 行程式碼,完成進度:%.2f %%\n離 10 萬行程式碼還差 %d 行,請繼續努力!' % (total, total/1000, 100000-total)
g.textbox(msg, title, text)
def calc_code(file_name):
lines = 0
with open(file_name) as f:
print('正在分析檔案:%s ...' % file_name)
try:
for each_line in f:
lines += 1
except UnicodeDecodeError:
pass # 不可避免會遇到格式不相容的檔案,這裡忽略掉......
return lines
def search_file(start_dir) :
os.chdir(start_dir)
for each_file in os.listdir(os.curdir) :
ext = os.path.splitext(each_file)[1]
if ext in target :
lines = calc_code(each_file) # 統計行數
# 還記得異常的用法嗎?如果字典中不存,丟擲 KeyError,則新增字典鍵
# 統計檔案數
try:
file_list[ext] += 1
except KeyError:
file_list[ext] = 1
# 統計原始碼行數
try:
source_list[ext] += lines
except KeyError:
source_list[ext] = lines
if os.path.isdir(each_file) :
search_file(each_file) # 遞迴呼叫
os.chdir(os.pardir) # 遞迴呼叫後切記返回上一層目錄
target = ['.c', '.cpp', '.py', '.cc', '.java', '.pas', '.asm']
file_list = {}
source_list = {}
g.msgbox("請開啟您存放所有程式碼的資料夾......", "統計程式碼量")
path = g.diropenbox("請選擇您的程式碼庫:")
search_file(path)
show_result(path)