歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

[anygui] 項目預覽---Anygui 將完成 Python 的最佳工具箱

  在 Python 世界中有一個非常有趣的 [anygui] 項目,它已經進入了早期的開發階段。[anygui] 項目打算作為許多主要圖形工具箱的下層 API。一旦完全開發成功,Python 程序員就可以調用公共 [anygui] 函數 — 例如,為創建一個窗口 — 可由“最適當好用”的工具箱來完成這項工作。在 Windows 上,可以使用到 Win32 API(或者 wxWindows);在 MacOS 上,可以本機調用;在 BeOS 上,使用 Bethon;在 Linux 上,使用 TKinter 或者 GTK;在 Telnet 屏幕上使用 ncurses — 所有這些都取決於給定的機器上安裝的和可用的軟件。本文討論了 [anygui] 當前的開發狀態,以及該項目要達到的目標。 編寫一次,到處顯示! 許多年前當 Java 剛出現時,它的一個重要承諾就是實現代碼“編寫一次,隨處運行”的想法。起先,主要考慮將 Java 用戶界面作為 applet,嵌入到 Web 浏覽器中。一段時間後,獨立的 AWT 應用程序成為更流行的概念。接下來,AWT 通常被 Swing 所取代。Swing 又變成了 Bean(構建在 Swing 上,但有另外的要求)。這樣依次下來,Swing 類從 Java 版本中添加、刪減,不斷來回變化著。 有關 Java 的一個很流行的笑話是,“編寫一次,到處調試”。至少可以確定的是,您不可能編寫了一個 Java 應用程序後,非常自信地認為它可以運行在您應用程序的每個用戶機器上 — 除非您願意要求每個用戶做相當多的工作來獲取 Java 版本和配置,使它們完全符合您特定的應用程序。應用程序是否運行取決於 Java 版本,以及甚至特定的供應商和安裝 Java 虛擬機(JVM)的平台。 就大多數方面而言,如 Python、Perl 和 Tcl 這樣的腳本語言,要比 Java 具有更好的可移植性。例如,對於大多數 Python 腳本,程序員感到十分自信的是,發送到多個用戶的腳本在每台目標機器上都將正確和完全一致地運行(可能有最低版本的要求 — 這要比 Java 上的要求簡單得多、可靠得多)。當然,Java 除了不完美的移植性外,它也有許多優勢:靜態輸入(許多人想要它)、龐大的類庫、卓越的文檔、細心的設計選擇。但是有關那些語言的注意事項並不是我在這裡感興趣的話題。 Python 腳本可移植性中有一個地方比 Java 差很多,那就是在用戶界面中。對於一個命令行工具,這一點不成問題。但當您希望復雜的用戶交互時 — 特別專門針對圖形界面時 — Python 實際上什麼也不能提供。對於所有的小故障和小錯誤,Java 通常確實為每個帶 JVM 的平台提供了 Swing 和 AWT 這些基本的 GUI。相反,Python 完全沒有任何“標准”的 GUI 庫。 許多人都表示他們期望有標准的 Python GUI。Tkinter 恰在這時到來 — 它有 Windows 和 UNIX/X Window 系統穩定的版本,並且有一個過得去的 MacOS 版本。但您還需要在系統上安裝 TCL 和 TK,以及被忽略的“非主流”平台,如 BeOS 和 OS/2。各類倡導者建議,采用一些其它庫/綁定將會是一個更好的選擇(有許多庫可以進行選擇;請參閱參考資料)。而每個庫/綁定支持一個期望平台的子集;並且最重要的是,沒有一個庫/綁定被一致地接受(因此,沒有一個成為標准而隨 Python 分發版一起發行)。我們無法編寫帶用戶界面的應用程序,並且無法確保實際 用戶可以與它進行相互操作。 重新考慮這個問題 Java 思想創建了每個 JVM 必須實現的能力的一個標准集合。Java GUI 是根據規定而存在。Python 式的方法可能來自一個不同的角度。不再命令每台機器遵從某個確定的 API,取而代之的是,只是確定給定機器可以做什麼,然後從那裡開始工作。API 僅作為底層平台所完成工作的包裝器。 一旦以 Python 方式考慮問題時,anygui 做了您確實希望做的事情。從 anydbm 模塊中取出它的名字和相關說明,在運行時找到“最適當可用”的數據庫後端, anygui 在自身應用程序正在運行的系統上會找到最適當可用的 GUI 後端。anygui 強調提供一個可以和每個後端一起工作的實用的界面元素集合;特定的後端可能自己能夠提供更高級的界面,但 anygui 提供的是它們的公共的界面。 寫本文的時候,anygui 還是一個 alpha 級的項目。對一個目標後端子集,anygui 已經做得非常好。但由於目標是建立一個(接近於)通用的包裝器,只有一個子集在工作顯然是不夠的。最終,如果 anygui 達到了它的目標,則在每個 Python 分發版中,anygui 都將作為標准的 Python 包包含在其中,那才是有意義的(就如同不管什麼依賴於系統的後端,Python 分發版中都包括了 anydbm 或者 XML.sax)。畢竟,這一點才能確保每個用戶都擁有了它。順便提一下, anygui 是純 Python;它本身不需要 C/C++ 或者其他較低級語言的任何東西(當然,如果有用,anygui 應該找一些支持的 GUI 庫)。


平台和圖片 為了寫本文,我快速研究了大多數工作後端。還有幾個後端沒有實現,或者只實現了部分功能。已經實現的有 Tkinter、Java Swing、win32all、PyGTK 和 wXPython。BeOS 本機(帶 Bethon)只實現了部分功能,但可能每天都構建一次進行新的改進。PyQT 和 MacOS 本機已經編制了規劃,並且已經進行了開發,還沒有創建這些包裝器的實現;當然,隨著時間的推移,這些都可能發生變化。關於直接的 xlib 後端,也一直有一些討論,但目前沒有人自願負責這項工作。 上面所有的圖形工具箱以一種非常相似的方式工作,或將以一種非常相似的方式工作。我承認我在大多數後端工具箱方面的知識很有限 — 但從我的理解,anygui API 在很大程度上與 Tkinter 相似。本質上,這個策略是創建帶回調的一串窗口小部件,然後進入一個主事件循環。 將來還可能會有一些其它後端,它們會打破這個“標准”的 GUI 工具箱模型。在某些方面,它們看起來似乎最有趣,或者至少很新穎。一個已經規劃好的後端被期望由我來負責 — 但是在開發最初的版本時,我有點懈怠。希望在您讀本文時,這會有所改進。我自己開發的小型後端是 ncurses。如果它最終實現,則這開創了甚至在文本模式的終端(譬如,SSH/telnet 會話)或者只是在純 UNIX 機器(不帶 X Window 系統)上運行 anygui 應用程序的可能性。 按照 curses 後端的風格,anygui 的項目負責人 Magnus Lie Hetland 已經建議了純面向行界面(似乎有點倒退),它可以使用 readlines 支持。在這個方案中,菜單將簡化成提示符,接著是選項選擇,再接著是反饋或者結果等等。假想中的 anygui.backends.textgui 只需要 STDIN 和 STDOUT 來工作,這對於程序來說,是令人感興趣的,因為它所需要的最少。否則,該程序可能(一點未變動)運行在復雜的圖形化、事件驅動和 WIMP 界面(窗口、圖標、鼠標指針)。當然,到目前為止,它還只是一個想法。 還有一個古怪的想法也同樣有趣。每人都有一個 Web 浏覽器(幾乎),即使那個浏覽器碰巧是 lynx 或者是 links。Python 標准的 webbrowser 模塊允許以一種與 anygui 以及和 anygui 具有相似功能的軟件的方式,靈活地啟動一個“最適當可用”的 Web 浏覽器。如果那個浏覽器與某類 LOCALHOST 服務器通信,那麼所有您想要的基本界面設備都完全在 Web 浏覽器內(按鈕、輸入域、文本區域、圖形等等)。這個後端也處於規劃階段。 一幅圖片抵得上用千言萬語來表達的含義(至少有時候)。由於我的編輯們,出於善意,不希望將本專題出版為一萬字的巨著,所以就讓我們看幾幅屏幕快照。為了說明需要,使用了一個小玩具應用程序,有一些按鈕,並且啟用了幾個不活動性的按鈕(它的源代碼顯示如下)。其中還包含了幾個文本標簽。其它窗口小部件示例包含在 anygui 分發版的 test 目錄中。 首先值得一看的,我們可能認為是作為“默認缺省值”的後端 Tkinter。這個版本看上去和使用起來就與它應該做到的完全一致。但是, win.destroy() 調用就有點好笑 — 它沒有立即破壞窗口(並且關閉應用程序),而是一旦當窗口受到足夠的注意(比如移動窗口),它就將窗口變為一個會消失的鬼怪。如同我說的,我們還停留在 alpha 階段。這個示例在 Win98 下運行: Tkinter 下的按鈕應用程序(在 Win98 上) 在 Windows 下運行時,還有一個利用 win32all 模塊使用 Windows 本機調用的選項。來自 ActiveState 的 ActivePython 分發版在缺省情況下有這個選項;否則,還需要另外獲得此模塊(也是來自 ActiveState)。總之,這種綁定是我看到的運行最好的一種 — 但那也只是反映在我做測試的版本上。標簽的放置與 Tkinter 上的有一點不同,這表示,一個人對不同後端不可能得到完全相同的視覺審美觀。 Win32 下的按鈕應用程序(在 Win98 上) 接下來,我決定將話題轉到一個完全不同的平台上。在 OS/2 Warp 4 下運行 Python,我得到了如下的結果。由於某些原因,在文本標簽前面多了一個不必要的 <Html>。盡管這是一個很小的錯誤,但令人印象深刻的是,同一段代碼運行在不同的平台上,結果竟然是如此的不同: Java Swing 下的按鈕應用程序(在 OS/2 Warp 4 上) 然後轉到 Linux 平台,在已經安裝了 PyGTK 的系統上運行相同一個應用程序。只為了好玩,我在幾個不同的 window 管理器下運行該應用程序。首先在 Enlightenment 上: GTK 下的按鈕應用程序(在 Enlightenment 上) 然後在 WindowMaker 上: GTK 下的按鈕應用程序(WindowMaker 上) 在不同窗口管理器下的窗口框架內所有東西都是相同的。標簽的對齊和尺寸與 Windows 下的有點不同(需要額外增加幾個像素,避免截斷字)。我無法很容易地在我任何一個系統上安裝 wxPython,但我想結果應該是相似的。 BeOS 後端還處於一種較原始的狀態。甚至玩具應用程序也失敗了。但是,基本的 Window 類工作得很好: BeOS r5 上的窗口測試應用程序 一些自身相同的代碼 這段運行在所有證明過的平台上的代碼非常簡單。在我的示例中,該程序的上半部分完全是實現一個 switch,允許從命令行手工選擇要使用的後端。在產品代碼中,您將不會希望有這樣的選擇;但對於早期的測試,就象我所做的這些,是很有幫助。然而請注意,這裡顯示的屏幕快照的這些所有測試完全在沒有任何命令行選項的情況下運行 — 後端的選擇是自動的。讓我們來看一下代碼:

[anygui] 的‘button.py’文本應用程序 import sys if len(sys.argv)==1or sys.argv[1].upper()=='DEFAULT': from anygui import Window, Button, Application, Label elif sys.argv[1].upper()=='TK': from anygui.backends.tkgui import Window, Button, Application, Label elif sys.argv[1].upper()=='MSW': from anygui.backends.tkgui import Window, Button, Application, Label elif sys.argv[1].upper()=='BEOS': from anygui.backends.beosgui import Window, Button, Application, Label elif sys.argv[1].upper()=='GTK': from anygui.backends.gtkgui import Window, Button, Application, Label elif sys.argv[1].upper()=='JAVA': from anygui.backends.javagui import Window, Button, Application, Label elif sys.argv[1].upper()=='WX': from anygui.backends.wxgui import Window, Button, Application, Label def say_hello(): global bye print"Hello, world!" bye._set_enabled(1) app = Application() win = Window(width=150, height=150, title="Beatles Lyric") win.add(Label(x=10, y=10, width=140, text = "I don't know why you say...")) bye = Button(x=30, y=40, width=70, height=30, text="Goodbye", action=lambda: win.destroy(), enabled=0) win.add(bye) win.add(Label(x=10, y=70, width=120, height=32, text = "When I say...")) hi = Button(x=30, y=100, width=70, height=30, text="Hello", action=say_hello) win.add(hi) win.show() app.run() 應用程序的主框架只由四個步驟組成:(1)創建一個應用程序;(2)創建一個或多個窗口;(3)在窗口中添加一些窗口小部件;(4)調用 app.run() 事件循環。窗口小部件選項都作為命名的參數傳遞。 結束語 在目前的 anygui alpha 版中已經有編寫基本“獲取一些數據,對它進行處理,並且顯示一些結果”的應用程序所需要的一切東西。討論列表中包含了許多關於更多細微差別的事件處理、視圖模型等有趣的主題。此外, anygui API 還需要正式的地編制文檔。然而在承諾方面,在很長一段時間內 anygui 與我看到的任何 Python 庫相比,更令我興奮。幾乎很難想象在 Python 自身運行的地方,它能夠透明地獲取復雜的用戶界面,這是多麼的方便 — 根本不需要為平台細節方面更改一行代碼。 參考資料 * 可以從 SourceForge 頁面開始探索 anygui。從那裡,可以浏覽到開發人員郵件列表、文檔、最新版本的下載等等。 * Cameron Laird 已經編寫了 Python 詳盡列表的 GUI 綁定。Laird 的列表包含了有關每個綁定的狀態以及到相關項目頁的鏈接的注釋摘要。 * 請查閱 Damond Walker 的 tinter 和 Laurent Pelecq 的 增強的 ctinter。curses 本身是一個標准 Python 模塊(它需要實際的 ncurses 庫來工作)。 * 在 developerWorks 上,David Mertz 編寫的與“可愛的 Python”專欄相關的文章還有 "Charming Python: TK programming in Python" 和 "Charming Python: Curses programming"。 * 請浏覽 developerWorks 上的更多 Linux 參考資料。 * 請浏覽 developerWorks 上的 更多開放源碼參考資料。 關於作者 David Mertz 一直致力於對各類知識進行融會貫通;唯一使他比看到一個好的交互式多媒體庫更高興的事是回到打卡和批處理系統的想法。可以通過 [email protected] 與 David 聯系;http://gnosis.cx/publish/ 上詳細地介紹了他的生活。非常歡迎對以前的、本篇和以後的專欄文章提出建議和意見。



參考資料 * 可以從 SourceForge 頁面開始探索 anygui。從那裡,可以浏覽到開發人員郵件列表、文檔、最新版本的下載等等。 * Cameron Laird 已經編寫了 Python 詳盡列表的 GUI 綁定。Laird 的列表包含了有關每個綁定的狀態以及到相關項目頁的鏈接的注釋摘要。 * 請查閱 Damond Walker 的 tinter 和 Laurent Pelecq 的 增強的 ctinter。curses 本身是一個標准 Python 模塊(它需要實際的 ncurses 庫來工作)。 * 在 developerWorks 上,David Mertz 編寫的與“可愛的 Python”專欄相關的文章還有 "Charming Python: TK programming in Python" 和 "Charming Python: Curses programming"。 * 請浏覽 developerWorks 上的更多 Linux 參考資料。 * 請浏覽 developerWorks 上的 更多開放源碼參考資料。 關於作者 David Mertz 一直致力於對各類知識進行融會貫通;唯一使他比看到一個好的交互式多媒體庫更高興的事是回到打卡和批處理系統的想法。可以通過 [email protected] 與 David 聯系;http://gnosis.cx/publish/ 上詳細地介紹了他的生活。非常歡迎對以前的、本篇和以後的專欄文章提出建議和意見。



* 在 developerWorks 上,David Mertz 編寫的與“可愛的 Python”專欄相關的文章還有 "Charming Python: TK programming in Python" 和 "Charming Python: Curses programming"。 * 請浏覽 developerWorks 上的更多 Linux 參考資料。 * 請浏覽 developerWorks 上的 更多開放源碼參考資料。 關於作者 David Mertz 一直致力於對各類知識進行融會貫通;唯一使他比看到一個好的交互式多媒體庫更高興的事是回到打卡和批處理系統的想法。可以通過 [email protected] 與 David 聯系;http://gnosis.cx/publish/ 上詳細地介紹了他的生活。非常歡迎對以前的、本篇和以後的專欄文章提出建議和意見。



Copyright © Linux教程網 All Rights Reserved