用wxPython創建GUI應用程序展示NASA圖片(第二部分)
NASA搜索應用的創建
快速原型是一種快速創建小而實用的應用程序的方法,無需花費大量時間實現所有部件,而是在應用中自上而下依次添加。相較於創建一系列嵌套的sizer,這種方法效率更高。
首先,讓我們創建一個名為nasa_search_ui.py的腳本:
這裡將導入一些新包。第一個是請求包,使用方便,基於Python實現文件下載和Internet相關操作,許多開發人員認為它比Python自帶的urllib更好用。不過它需要安裝才能使用,同時還需要安裝ObjectListView。
如下是使用pip的安裝方法:
另外,需要導入urllib.parse,用於編碼URL參數。最後,DownloadDialog是一個用於創建對話的類,用於NASA圖像的下載。
由於在應用中將使用ObjectListView,因此需要一個類來表示該窗口部件中的對象:
Result類用於保存構成ObjectListView中每行的數據。Item參數是查詢響應JSON的一部分。您可以根據需求解析相關信息。
在這種情況下,需要如下欄位:
- 標題
- 圖片位置
- NASA內部ID
- 照片描述
- 攝影師名稱
- 圖像創建時間
- 縮略圖URL
其中一些項並不總是包含在JSON響應中,在這些情況下,將通過get()方法返回空字元串。
下面將開始UI的實現:
MainPanel是程序的主體。這裡,您可以處理一些內務工作並創建一個search_results,以便用戶搜索時保存Result對象列表。您還可以設置縮略圖的max_size,要使用的字體,sizer以及標準路徑等。
下面將如下代碼加入__init__()中:
這裡,使用wx.StaticText為應用程序創建標題標籤。然後,添加了wx.SearchCtrl,其與wx.TextCtrl非常類似,只不過內置了特殊的按鈕。此外還將搜索按鈕的單擊事件(EVT_SEARCHCTRL_SEARCH_BTN)和EVT_TEXT_ENTER綁定到搜索相關的事件處理程序(on_search)。
接下來添加搜索結果部件:
這段代碼設置ObjectListView的方式和我的其他一些文章中的方式非常相似。您可以通過調用SetEmptyListMsg()來自定義空消息,還可以將窗口部件綁定到EVT_LIST_ITEM_SELECTED,以便用戶在選擇搜索結果時執行某些操作。
下面將其餘代碼加入__init__()中:
最後幾行代碼添加了標題文本控制項和圖像窗口部件,這些部件將在選擇結果時更新。您還可以添加下載按鈕,以允許用戶選擇要下載圖像的大小。NASA通常會提供從縮略圖到原始TIFF圖之間的幾種不同版本的圖像。
要查看的首個事件處理程序是on_download():
這裡,通過調用GetSelectedObject()來獲取用戶的選擇。如果用戶未選擇任何內容,則退出此方法。此外,如果用戶選擇了某個條目,則實例化DownloadDialog並將其展示給用戶以允許他們下載某些內容。
下面將學習如何實現搜索:
這裡,on_search()事件將獲取用戶輸入的字元串或者返回一個空字元串。假設用戶實際輸入了要搜索的內容,則使用NASA的常規搜索查詢,q並對media_type進行硬編碼以實現成像。之後,將查詢編碼為格式正確的URL,並通過requests.get()來請求JSON響應。
接下來,將嘗試循環搜索結果。請注意,如果不返回任何數據,代碼將運行失敗並拋出異常。如果返回數據,可以對其進行解析以獲取所需信息。
您將跳過未設置標題欄位的項目。否則,將創建一個Result對象並將其添加到search_results列表中。在方法結束時,需要通知UI更新搜索結果。
在使用該函數之前,需要創建on_selection():
您將再次獲得所選條目,但是這次採用選擇標題文本進行選擇並更新標題文本控制。然後檢查是否存在縮略圖並更新(如果有)。如果無縮略圖,則設置為空圖像,因為您不希望它繼續顯示之前選擇的圖像。
下一個要創建的方法是update_image():
這裡,update_image()接收URL作為其唯一的參數。它接收此URL並拆分文件名。然後通過計算機的臨時目錄創建一個新的下載位置。接著下載圖像並檢查文件是否存儲正確。如果是,則使用設置的max_size載入縮略圖;否則將設置為空白圖像。
最後幾行代碼Refresh()和Layout()面板,使得部件能正確顯示。
最後,您需要創建最後一個方法:
這裡,將創建框架,設置標題和初始大小並添加面板,之後顯示框架。
主UI的外觀如下:
下面讓我們一起學習如何實現下載對話框吧!
下載對話框
下載對話框將允許用戶下載一個或多個圖像,每張圖像至少存在兩個甚至五六個版本。
先看一下代碼的前幾行:
這裡將再次導入requests並在保存圖像時設置wildcard。
下面將創建__init__():
在此示例中,您將創建StandardPaths的新引用並添加wx.ListBox。列表框將包含可下載圖像的變數。如果結果太多無法同時顯示,它還會自動添加滾動條。通過傳入selection對象調用get_image_urls以獲取URL列表,然後遍歷urls並提取名稱中包含jpg的urls。這將導致遺漏其他圖像文件類型,例如PNG或TIFF。
因此可以對此代碼進行改進。過濾URL的原因在於排除非圖像URL,以免給用戶帶來困惑。
最後還需要添加一個「保存」按鈕,當然也可以添加「取消」按鈕,但是由於對話框頂部已經包含退出按鈕,所以沒必要。
下面來了解以下get_image_urls()的作用:
當用戶按下「保存」按鈕時,將激活此事件處理程序。當用戶嘗試保存某些內容而不在列表框中選擇條目時,將返回-1。如果發生此類情況,將通過MessageDialog告知用戶進行選擇。當用戶選擇某些內容時,將展示一個wx.FileDialog,允許用戶選擇保存文件的位置以及調用內容。
如下是save()方法:
這裡,您將再次使用requests下載圖像。注意,這裡並未對用戶是否添加擴展名做出檢查,請使用右側擴展名。如果可以的話,請自行添加。
當文件下載完成後,向用戶展示一條提示信息。
如果發生異常,您也可以顯示一個對話框通知用戶!
對話框的樣式如下:
接下來讓我們添加一些新功能吧!
添加高級搜索
您可以使用幾個欄位來縮小查詢範圍。但是除非用戶確實想使用這些過濾器,否則盡量不要用此來擾亂用戶界面的設計。為了解決這個問題,可以添加「高級搜索」選項。
添加這個功能需要重新組織代碼,因此這裡將nasa_search_ui.py和download_dialog.py複製到名為version_2的新文件夾中。
接下來將nasa_search_ui.py重命名為main.py作為程序的入口。為了使程序更加模塊化,可以將搜索結果提取到自己的類中,並在單獨的類中進行高級搜索。這意味最終將需要三個面板:
- 主面板
- 搜索結果面板
- 高級搜索麵板
實現後的對話框樣式如下:
接下來將分別討論這些問題。
main.py腳本
main模塊是應用程序的入口,是為了啟動應用程序而運行的代碼。如果要將應用程序綁定到可執行文件中,也可以使用它。
如下是main模塊:
這個示例導入了兩個與搜索相關的面板:
- AdvancedSearch
- RegularSearch
它還使用pubsub訂閱更新主題。
讓我們探索一下__init__()中包含的其他內容:
這裡,可以像之前那般為頁面添加標題和搜索部件,還可以添加新的「高級搜索」按鈕,並使用新的sizer來包含搜索部件和按鈕。然後將sizer添加到主sizer中。
接下來讓我們添加面板:
在此示例中,將實例化RegularSearch和AdvancedSearch面板。由於RegularSearch是默認值,因此在啟動時隱藏了用戶的AdvancedSearch。
現在更新on_search():
當用戶按下「輸入/返回」時將調用on_search()。如果用戶在搜索框中輸入搜索條件,則將構建查詢,並通過pubsub發送。
當用戶按下Advanced Search按鈕,會發生什麼呢?
當觸發on_advanced_search()時,會隱藏搜索部件,常規搜索麵板以及高級搜索按鈕。接下來,將顯示高級搜索麵板並在main_sizer上調用Layout(),因此面板將會進行切換並調整以適應框架大小。
最後需要創建update_ui()方法:
當用戶執行Advanced Search時,將調用update_ui()方法,此方法由pubsub調用。它會執行on_advanced_search(),取消顯示高級搜索麵板時隱藏的所有窗口部件,當然它也可以隱藏高級搜索麵板。
框架代碼與之前相同,因此這裡並未展示。
下面讓我們接著學習如何實現常規搜索麵板吧!
英文原文:https://www.blog.pythonlibrary.org/2019/04/18/creating-a-gui-application-for-nasas-api-with-wxpython/ 譯者:我是昵稱耶~
※如何在不停機的情況下在Django中創建索引
※讀懂Python的Mock對象庫(2)
TAG:Python部落 |