• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 用于 Python 的高級 GUI 庫

    發表于:2007-07-04來源:作者:點擊數: 標簽:
    Qt 工具箱是一個使用廣泛的跨平臺 GUI 工具箱,可用于 Windows、Linux、Mac OSX 和許多手持平臺。QT 具有良好結構化(但靈活)的 面向對象 的結構、清晰的文檔以及直觀的 API。本文中,David Mertz 和 Boudewijn Rempt 探討了 Qt 庫,集中討論了允許 Python

    Qt 工具箱是一個使用廣泛的跨平臺 GUI 工具箱,可用于 Windows、Linux、Mac OSX 和許多手持平臺。QT 具有良好結構化(但靈活)的面向對象的結構、清晰的文檔以及直觀的 API。本文中,David Mertz 和 Boudewijn Rempt 探討了 Qt 庫,集中討論了允許 Python 程序員訪問 Qt 功能的 PyQt 綁定。
    一般來說,選擇用于應用程序的 GUI 工具箱會是一件棘手的事。使用 Python(許多語言也一樣)的程序員可以選擇的 GUI 工具箱種類繁多,而每個工具箱都有各自的優缺點。有些速度比其它工具箱快,有些比較??;有些易于安裝,有些更適合于跨平臺使用(對于這一點,還要指出,有些支持您需要滿足的特定特性)。當然,各種庫都相應具有各種許可證。

    對于 Python 程序員而言,缺省的 GUI 選擇是 Tk(通過 Tkinter 綁定)— 其原因顯而易見。Tkinter 和閑置的 IDE 是由 Python 創始人編寫的,它們是作為大多數 Python 分發版的缺省選擇而出現的。標準 Python 文檔討論了 Tkinter,但沒有涉及任何其它 GUI 綁定。這是故意的!至少可以這么認為,如果 Tk 和 Tkinter 不是這么糟糕,程序員就沒有理由去尋找替代品了。要誘導 Python 程序員放棄缺省選擇,那么工具箱必須提供額外的東西。PyQt 就是這樣一個工具箱。

    PyQt 所具有的優點遠遠超過了 Tkinter(它也有幾個缺點)。Qt 和 PyQt 速度都很快;Qt 和 PyQt 的設計完全是面向對象的;Qt 提供了一個設計良好的窗口構件集合,它比 Tk 所提供的要大得多。就其缺點而言,Qt 的許可證受到的限制比許多工具箱(至少在非 Linux 平臺方面)都多;正確安裝 Qt 和 PyQt 常常會很復雜;另外,Qt 是一個相當大的庫。PyQt 應用程序的用戶將需要設法完成安裝 Qt 和 PyQt,這使分發變得很困難。(請閱讀本文后面的用于其它語言的 Qt 綁定。)

    PyQt 嚴格遵循 Qt 的發放許可。特別是,它可用于 UNIX/X11 平臺上的 GPL,并可用于 Zaurus 上的 Qt Palmtop Environment 環境,還存在用于較老的 Qt 版本的免費(free-as-in-free-beer)Windows 軟件包。PyQt 的商業許可證可用于 Windows。

    對于本文而言,PyQt 有一個方面優于許多其它工具箱,它值得我們特別關注。Qt 使用一種稱為信號/插槽(signals/slots)的機制在窗口構件(以及其它對象)之間傳遞事件和消息。這種機制完全不同于包括 Tkinter 在內的大多數工具箱所用的回調(callback)機制。使用信號/插槽以靈活且可維護的方式控制對象間通信要比使用脆弱的回調風格容易得多。應用程序越大,Qt 的這個優勢就越重要。

    本文的作者之一 Boudewijn Rempt 已經出版了一本有關使用 PyQt 進行應用程序開發的書籍。GUI Programming with Python: QT Edition(請參閱參考資料)顯示了如何設計和開發完整的 GUI 應用程序,其中包括從最初的構思到分發的全過程。

    樣本應用程序
    要顯示信號/插槽和回調之間的反差,我們提供了一個寫著玩玩的應用程序,它使用 Tkinter 和 PyQt。盡管實際上 PyQt 版本對于這個基本程序并不更簡單,但是它已經演示了 PyQt 應用程序更好的模塊性和可維護性。

    應用程序包括四個窗口構件:

    “Quit”按鈕(用來與整個應用程序通信)
    “Log Timestamp”按鈕(用于窗口構件間的消息)
    文本區域,顯示可滾動的已記錄日志的時間戳記列表
    消息窗口構件,顯示已記錄日志的時間戳記數
    在 Tkinter 中,我們可以這樣實現應用程序:


    清單 1. Logger.py Tkinter 應用程序 #!/usr/bin/python
    import sys, time
    from Tkinter import *

    class Logger(Frame):
        def __init__(self):
            Frame.__init__(self)
            self.pack(expand=YES, fill=BOTH)
            self.master.title("Timestamp logging application")
            self.tslist = []
            self.tsdisp = Text(height=6, width=25)
            self.count = StringVar()
            self.cntdisp = Message(font=('Sans',24),
                                   textvariable=self.count)
            self.log = Button(text="Log Timestamp",
                              command=self.log_timestamp)
            self.quit = Button(text="Quit", command=sys.exit)
            self.tsdisp.pack(side=LEFT)
            self.cntdisp.pack()
            self.log.pack(side=TOP, expand=YES, fill=BOTH)
            self.quit.pack(side=BOTTOM, fill=BOTH)
        def log_timestamp(self):
            stamp = time.ctime()
            self.tsdisp.insert(END, stamp+"")
            self.tsdisp.see(END)
            self.tslist.append(stamp)
            self.count.set("% 3d" % len(self.tslist))

    if __name__=='__main__':
        Logger().mainloop()
     


    這個 Tk 版本使用了 log_timestamp() 方法作為按鈕的 command= 參數。這個方法需要依次單獨操作它要影響的所有窗口構件。如果我們想更改按鈕按下的效果(例如還要記錄時間戳記),那么這個風格就很脆弱。通過繼承您可以實現這一點:

    清單 2. StdOutLogger.py Tkinter 增強 class StdOutLogger(Logger):
        def log_timestamp(self):
            Logger.log_timestamp(self)
            print self.tslist[-1]
     


    但是這個子類的作者需要相當精確地理解 Logger.log_timestamp() 已經做了什么;而且除非通過在子類中完全重寫 .log_timestamp() 方法并且不調用父方法,否則沒有辦法除去消息。

    一個非?;镜?PyQt 應用程序總有一些樣本代碼,這些代碼在哪里都相同,Tkinter 代碼也是這樣。但是,當我們進一步研究設置應用程序所需的代碼,以及顯示窗口構件的代碼時,區別就顯現出來了。

    清單 3. logger-qt.py PyQt 應用程序 #!/usr/bin/env python
    import sys, time
    from qt import * # Generally advertised as safe

    class Logger(QWidget):
        def __init__(self, *args):
            QWidget.__init__(self, *args)
            self.setCaption("Timestamp logging application")
            self.layout = QGridLayout(self, 3, 2, 5, 10)
            self.tsdisp = QTextEdit(self)
            self.tsdisp.setMinimumSize(250, 300)
            self.tsdisp.setTextFormat(Qt.PlainText)
            self.tscount = QLabel("", self)
            self.tscount.setFont(QFont("Sans", 24))
            self.log = QPushButton("&Log Timestamp", self)
            self.quit = QPushButton("&Quit", self)
            self.layout.addMultiCellWidget(self.tsdisp, 0, 2, 0, 0)
            self.layout.addWidget(self.tscount, 0, 1)
            self.layout.addWidget(self.log, 1, 1)
            self.layout.addWidget(self.quit, 2, 1)
            self.connect(self.log, SIGNAL("clicked()"),
                         self.log_timestamp)
            self.connect(self.quit, SIGNAL("clicked()"),
                         self.close)
        def log_timestamp(self):
            stamp = time.ctime()
            self.tsdisp.append(stamp)
            self.tscount.setText(str(self.tsdisp.lines()))
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        app.connect(app, SIGNAL('lastWindowClosed()'), app,
                      SLOT('quit()'))
        logger = Logger()
        logger.show()
        app.setMainWidget(logger)
        app.exec_loop()
     


    通過創建布局管理器,Logger 類開始工作了。布局管理器在任何 GUI 系統中都是一個很復雜的主題,但是 Qt 的實現使之變得簡單。在大多數情況下,您會使用 Qt Designer 創建一般的 GUI 設計,隨后可將它用于生成 Python 或 C++ 代碼。然后您可以使生成的代碼生成子類,以添加功能。

    但是在這個示例中,我們選擇手工創建布局管理器。窗口構件被置于網格的各個單元中,或者可以跨多個單元放置。在 Tkinter 需要命名參數的地方,PyQt 就不允許它們。這是一個很重要的差異,它經常會使在兩種環境中工作的人們無所適從。

    所有 Qt 窗口構件都可以和 QString 對象很自然地一起工作,而不能和 Python 字符串或 Unicode 對象一起工作。幸運的是,轉換是自動的。如果您在 Qt 方法中使用了字符串或 Unicode 參數,那么它將自動轉換成 QString。不能進行反向轉換:如果您調用了一個返回 QString 的方法,那么您獲得的是 QString。

    應用程序中最有趣的部分是我們將 clicked 信號連接到功能的位置。一個按鈕連接到了 log_timestamp 方法;另一個連接到了 QWidget 類的 close 方法。

    圖 1. logger-qt 的屏幕快照


    現在我們想將日志記錄添加到這個應用程序的標準輸出。這十分容易。我們可以使 Logger 類生成子類,或者為了演示,創建簡單的獨立函數:

    清單 4. logger-qt.py PyQt 增強 def logwrite():
        print(time.ctime())

    if __name__ == "__main__":
       app = QApplication(sys.argv)
       app.connect(app, SIGNAL('lastWindowClosed()'), app,
                   SLOT('quit()'))
       logger = Logger()
       QObject.connect(logger.log, SIGNAL("clicked()"), logwrite)
       logger.show()
       app.setMainWidget(logger)
       app.exec_loop()
     


    從上述代碼我們可以看到,這就是將 log QPushButton 的 clicked() 信號連接到新函數的事情。注:信號也可以將任何數據傳送到它們所連接的插槽,盡管在這里我們沒有顯示這樣的示例。

    如果您不想調用原始方法,那么可以從插槽 disconnect 信號,例如通過在 logger.show() 行之前添加以下行:

    清單 5. logger-qt.py PyQt 增強 QObject.disconnect(logger.log, SIGNAL("clicked()"),
                       logger.log_timestamp)
     


    現在將不再更新 GUI。

    用于 Python 的其它 GUI 綁定
    PyQt 在給定實例中可能不是很有用,可能是許可證狀態問題,也可能是平臺可用性問題(或者,可能因為再分發很困難,例如大小很大)。由于這個原因(也為了比較),我們想指出一些用于 Python 的其它流行 GUI 工具箱。

    Anygui
    Anygui 實際上不是 GUI 工具箱,而是一個作用于大量工具箱(甚至是令人驚奇的象 curses 和 Java/Jython Swing 那樣的工具箱)的抽象包裝器。在編程風格方面,使用 Anygui 類似于使用 Tkinter,但是要選中這個底層工具箱,要么自動進行,要么進行配置調用。Anygui 很好用,因為它允許應用程序未經更改就可以運行在差異很大的平臺上(但因此它支持受支持工具箱的“最低級公共特性”)。
    PyGTK
    PyGTK 綁定包裝了 GPL 下使用的 GTK 工具箱,它是流行的 Gnome 環境的基礎。GTK 在根本上是 X Window 工具箱,但是它還有 Win32 的 beta 級支持和 BeOS 的 alpha 級支持。在常規范例中,PyGTK 對窗口構件使用回調。綁定存在于 GTK 和大量編程語言之間,而不僅僅是 Qt,或甚至是 Tk。
    FXPy
    Python 綁定 FXPy 包裝了 FOX 工具箱。FOX 工具箱已經被移植到大多數類 UNIX 平臺上,以及 Win32 上。與大多數工具箱類似,FOX 和 FXPy 都使用回調范例。FOX 由 LGPL 特許。
    wxPython
    這個綁定包裝了 wxWindows 工具箱。與 FOX 或 GTK 類似,wxWindows 被移植到 Win32 和類 UNIX 平臺上(但是沒有移植到 MacOS、OS/2、BeOS 或其它“次要”平臺上 — 盡管它對 MacOSX 的支持是 alpha 級的)。在范例方面,wxPython 接近回調風格。wxPython 對繼承結構的關注程度高于大多數其它工具箱,而且它使用“事件”,而不是回調。但是本質上,事件仍舊被連接到單個方法上,隨后可能需要作用于各種窗口構件。
    win32ui
    win32ui 屬于 win32all 軟件包,它包裝了 MFC 類。很顯然,這個工具箱是特定于 Win32 的庫。MFC 實際上不只是 GUI 工具箱,它還使用各種范例的混合。對于想創建 Windows 應用程序的讀者而言,與其它工具箱相比,win32ui 會讓您“更接近于實質”。

    從其它語言使用 Qt
    如同 Python,從大量其它編程語言使用 Qt 工具箱是可能的。如果可以自由選擇,我們會首選 Python,而不是其它語言。諸如公司政策以及與其它代碼庫連接之類的外部約束可以決定編程語言的選擇。Qt 的原始語言是 C++,但也有用于 C、Java、Perl 和 Ruby 的綁定。就與 Python 示例的比較而言,讓我們討論一下用 Ruby 和 Java 寫著玩玩的應用程序。

    Ruby/Qt 在用法上十分類似于 PyQt。這兩種語言具有相似的動態性和簡明性,所以除了拼寫上的差別外,其代碼很類似:

    清單 6. HelloWorld.rb Qt2 應用程序 #!/usr/local/bin/ruby
    require 'qt2'
    include Qt2
    a = QApplication.new([$0] + ARGV)
    hello = QPushButton.new('Hello world!')
    hello.resize(100, 30)
    a.connect( hello, QSIGNAL('clicked()'), a, QSLOT('quit()'))
    a.setMainWidget(hello)
    hello.show
    a.exec
     


    Java 總是比腳本編制語言要冗長一點,但是基本部分都相同。一個同等功能的最小 qtjava 應用程序類似于:

    清單 7. HelloWorld.java Qt2 應用程序 import org.kde.qt.*;
    public class HelloWorld {
      public static void main(String[] args)
      {
        QApplication myapp = new QApplication(args);
        QPushButton hello = new QPushButton("Hello World", null);
        hello.resize(100,30);
        myapp.connect(hello, SIGNAL("clicked"),
                      this, SLOT("quit()"));
        myapp.setMainWidget(hello);
        hello.show();
        myapp.exec();
        return;
      }
      static {
        System.loadLibrary("qtjava");
        try {
            Class c = Class.forName("org.kde.qt.qtjava");
        } catch (Exception e) {
            System.out.println("Can't load qtjava class");
        }
      }
    }
     


    PyQt 是一個吸引人和快速的接口,它將 Qt 工具箱和 Python 編程語言集成在一起。除了該工具箱提供的種類繁多的窗口構件外,Qt 所用的信號/插槽編程風格在生產能力和可維護性方面都要優于大多數其它 GUI 工具箱所用的回調風格。

    參考資料

    從 Riverbank 訪問 PyQt 頁面。


    GUI programming with Python(OpenDocs;2001 年)頁面包含有關 Boudewijn Rempt 所寫書籍的信息,以及有關 PyQt 的更多信息。


    依照 Python.org,Tkinter 是 Python 的實際標準 GUI。在 David 撰寫的 developerWorks 文章“可愛的 Python:Python 中的 TK 編程 ”中,您也可以了解關于它的更多信息。


    通常不需要下載 IDLE(因為目前它與每個 Python 分發版捆綁在一起),除非您想使用實驗版本或其它非標準的版本。如果是這樣的話,您可以在 Python.org 的 IDLE 頁面上找到這樣的版本。


    在 SourceForge 您會找到 Anygui,David 撰寫的 developerWorks 文章“可愛的 Python:[anygui] 項目預覽”中對它進行了概述。


    您會發現 Cameron Laird's personal notes on Python GUIs 也很有趣。


    用于 GTK 窗口構件集的 Python 綁定(Python Bindings for the GTK Widget Set,或簡稱 PyGTK)提供了到流行的 GKT 窗口構件集的面向對象接口。


    FXPy 是一個擴展模塊,它提供了到 FOX GUI 庫的接口。


    如果您必須使用 wxWindows C++ 類庫,那么您會發現 wxPython 非常有幫助。


    win32ui 模塊封裝了 Microsoft Foundation Class。它是分布式的,它和 Pythonwin 都屬于 win32all 安裝軟件包。


    在 developerWorks Linux 專區查找更多 Linux 開發人員資料。

    關于作者
    Boudewijn Rempt 編寫了一本有關 PyQt 的書籍,已由 Opendocs 出版,書名為 GUI Programming with Python: QT Edition。在印刷出版的文檔中,本書的實用性將 PyQt 提升到與 Tkinter 同等的位置??梢酝ㄟ^ boud@valdyas.org 與 Boudewijn 聯系。

    David Mertz 希望百花齊放??梢酝ㄟ^ mertz@gnosis.cx 與 David 聯系;http://gnosis.cx/publish/ 介紹了他的生活。歡迎對過去的、這一篇或將來的專欄文章提出意見和建議。請訪問他即將出版的書籍 Text Processing in Python 的 Web 頁面。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>