PyQt
PyQt是Python語言的GUI編程解決方案之一。可以用來代替Python內建的Tkinter。其它替代者還有PyGTK、wxPython等。與Qt一樣,PyQt是一個自由軟體。PyQt是PyKDE的基礎。
開發者 | Riverbank Computing |
---|---|
首次發布 | 1998 |
目前版本 | 6.7.0[1](2024年4月26日,7個月前) |
程式語言 | C++ / Python[2] |
作業系統 | 跨平台 |
許可協定 | GNU GPL和商業授權 |
網站 | riverbankcomputing.com |
PyQt的開發者是英國的「Riverbank Computing」公司。與4.5版本之前的Qt一樣,它提供了GPL與商業協定兩種授權方式,因此它可以免費地用於自由軟體的開發。不過目前尚不提供LGPL授權方式。PyQt可以執行於Microsoft Windows、Mac OS X、Linux以及Unix的多數變種上。
2009年8月,Qt的開發公司諾基亞發布PySide,提供與PyQt類似的功能,但提供了LGPL授權。主要原因是「Riverbank Computing」不願以LGPL授權發布PyQt。[3]
自4.5版本以後[4],PyQt同時支援Python 2.x與Python 3.x。但是在API方面有所區別,最主要的是執行在Python 3.x下的PyQt不使用QString
,而是str
。另外,之前為了避開Python 2.x關鍵詞限制的exec_()
、print_()
兩個函式現在重新命名為exec()
,print()
。
PyQt組件
PyQt包含了大約440個類型、超過6000個的函式和方法。
- 「QtGui」模組包含了大多數的GUI類型。包含按鈕、文字方塊、列表等常見控制項,還包含了基於MVC設計模式的列表、表格、樹型控制項。同時還提供了一個能夠容納成千上萬個元素的畫布控制項,其中可以放置各種控制項和圖形。此外,QtGui還支援介面動畫與介面狀態機編程。
- 「QtNetwork」模組可以用於編寫非阻塞式的UDP、TCP程式。還包含了DNS、HTTP與FTP的客戶端。
- 「QtOpenGL」模組允許Qt程式使用OpenGL彩現3D圖形,而且不必大量更改代碼。
- 「QtWebkit」與「QtScript」兩個子模組支援WebKit與ECMAScript手稿語言
- 「Phonon」子模組支援進階的多媒體編程。包含音訊播放器、影片播放器與聲效處理。
- 「uic」子模組能夠將Qt的表單檔案轉換為Python代碼,能夠即時讀入表單檔案並且顯示出來。它依賴於QtXml模組。「QScintilla」子模組包含一個基於Scintilla的文字編輯器控制項,Eric IDE使用它作為代碼編輯器。「QtMultimedia」提供了底層的多媒體支援,現在多數開發者改用Phonon模組。「QtSvg」支援SVG 1.2 Tiny的靜態標準,用於顯示與儲存SVG格式的圖形。
簡單例子
下面一段代碼演示了一個簡單的PyQt程式,它的功能是在表單內顯示一個按鈕,當按下按鈕時,要求使用者輸入名字。根據使用者是否輸入了名字,會分別顯示兩種問候語。
# -*- coding: utf-8 -*-
#该程序适合Python 2.x
import sys
from PyQt4.QtGui import *
class TestWidget(QWidget):
def __init__(self):
QWidget.__init__(self, windowTitle=u"A Simple Example for PyQt.")
self.outputArea=QTextBrowser(self)
self.helloButton=QPushButton(self.trUtf8("问候(&S)"), self)
self.setLayout(QVBoxLayout())
self.layout().addWidget(self.outputArea)
self.layout().addWidget(self.helloButton)
self.helloButton.clicked.connect(self.sayHello)
def sayHello(self):
yourName, okay=QInputDialog.getText(self, self.trUtf8("请问你的名字是?"), self.trUtf8(b"名字"))
if not okay or yourName==u"": #用户没有输入名字,或者是点了取消
self.outputArea.append(self.trUtf8("你好,陌生人!"))
else:
self.outputArea.append(self.trUtf8("你好,<b>%1</b>。").arg(yourName))
app=QApplication(sys.argv)
testWidget=TestWidget()
testWidget.show()
sys.exit(app.exec_())
signal和slot
Qt採用了signal和slot的概念來處理GUI程式中的使用者事件。PyQt同樣支援這種方法,還進而針對Python的特點增強了某些功能。任何Python類型都可以定義signal和slot,並與GUI控制項的signal和slot相連接。PyQt支援old-style與new-style兩種連接方式。不過,目前一般推薦使用new-style connection。因為它還支援連接到Python函式,而且看起來也比較pythonic。
#old-style connection,
self.connect(self, SIGNAL("mySignal(int)"), self, SLOT("mySlot(int)"))
#new-style connection
self.mySignal.connect(self.mySlot)
#连接到函数
self.mySignal.connect(lambda value:sys.stdout.write(str(value)))
QMetaObject.connectSlotsByName(obj)
函式可以幫助程式設計師自動連接signal和slot。使用它可以免去很多代碼。
Qt設計器
Qt設計器是Qt所包含的視覺化UI設計器。在安裝PyQt時,可以選擇安裝Qt設計器。它使用拖拉操作來設計圖形介面。在設計的同時,還能夠直接預覽最終的表單效體。當表單很複雜或者整個程式需要大量的表單時,Qt設計器可以節省大量的代碼。不過稍有改變的是,設計好表單後需要執行pyuic4這個指令碼,將表單檔案轉換成Python代碼。仍以「簡單例子」中的小程式為例,首先使用Qt設計器設計出表單。假定儲存為"h:\pyqt_example.ui"。表單檔案內容是:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TestWidget</class>
<widget class="QWidget" name="TestWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>361</width>
<height>271</height>
</rect>
</property>
<property name="windowTitle">
<string>A Simple Example for PyQt.</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="outputArea"/>
</item>
<item>
<widget class="QPushButton" name="helloButton">
<property name="text">
<string>问候(&S)</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
使用如下命令將表單檔案轉換成Python代碼(適用於Windows系統):
H:\> C:\Python26\pyuic4.bat -o ui_pyqt_example.py pyqt_example.ui
新的範例程式是(假定儲存為h:\pyqt_example.py):
# -*- coding: utf-8 -*-
#该程序适合Python 2.x版本。
import sys
from PyQt4.QtGui import *
#差异1:从转换后的代码里面导入窗体
from ui_pyqt_example import Ui_TestWidget
#差异2:需要继承Ui_TestWidget
class TestWidget(QWidget, Ui_TestWidget):
def __init__(self):
QWidget.__init__(self)
#差异3:原来长篇累牍的创建控件的代码不再需要了,取而代之的是一行简单的setupUi()
self.setupUi(self)
self.helloButton.clicked.connect(self.sayHello)
def sayHello(self):
yourName, okay=QInputDialog.getText(self, self.trUtf8("请问你的名字是?"), self.trUtf8(b"名字"))
if not okay or yourName==u"": #用户没有输入名字,而是点了取消
self.outputArea.append(self.trUtf8("你好,陌生人!"))
else:
self.outputArea.append(self.trUtf8("你好,<b>%1</b>。").arg(yourName))
app=QApplication(sys.argv)
testWidget=TestWidget()
testWidget.show()
sys.exit(app.exec_())
PyQt的優劣
優勢
- PyQt的API與Qt類似,Qt的文件通常仍然可以應用於PyQt。因此,PyQt的文件比PyGTK、wxPython、Tkinter等GUI編程庫的文件豐富得多。
- 如果程式設計師具備使用Qt的經驗,一般很快就可以過渡到PyQt上。而使用PyQt的程式設計師,如果同時精通C++的話,也可以很快地過渡到Qt平台上。
- 利用SIP,大多數為Qt開發的控制項可以方便地port到PyQt。——然而,SIP也需要一些學習成本。
- 有方便的周邊工具支援PyQt。如QtDesigner,可以使用拖拉式的方法來設計介面,簡單易用。Eric6,一個使用PyQt設計的Python IDE,對PyQt有特殊的支援。
劣勢
- 由於PyQt同時使用Qt以及Python的兩種主記憶體管理方法,所以在使用PyQt的過程中要注意避免主記憶體洩露以及懸掛指標[5]。
- 執行時龐大,在Windows平台,只使用PyQt.QtCore與PyQt.QtGui兩個子模組時,壓縮後至少需要4.09M
- 需要學習一些C++知識,主要是C++類型、主記憶體管理兩個方面,以便於閱讀Qt文件和理解PyQt的行為。
SIP
SIP是一個自動為C和C++庫生成Python擴充模組的工具。為了方便開發PyQt,SIP於1998被「Riverbank Computing」公司創造出來。不過,SIP不專用於PyQt,而是適用於所有的C和C++庫。
使用SIP時,程式設計師首先要編寫一個特殊的".sip"檔案,使用類似於C++的語法在其中描述擴充模組所提供的類型與函式。然後用SIP將這個檔案轉化為C++代碼。最終編譯,與C、C++庫連結後就成為Python擴充模組。".sip"檔案類似於C、C++的標頭檔。根據需要,需要程式設計師用SIP定義的語法添加一些C++代碼中沒有的資訊。因為SIP不支援完整的C++語法,所以不能直接使用C++的標頭檔作為".sip"檔案。
使用PyQt的著名應用程式
- Eric Python IDE
- Anki, a spaced repetition flashcard program
- QtiPlot, a computer program to analyze and visualize scientific data
- qt-recordMyDesktop:recordMyDesktop的Qt4介面
- Kodos, Python Regular Expression Debugger
參考文獻
- ^ PyQt v6.7.0 Released.
- ^ PyQt4 Download. Riverbankcomputing. 2010 [2010-04-19]. (原始內容存檔於2010-02-21).
- ^ PySide has been released – PySide – Python for Qt. Pyside.org. 2009-08-18 [2009-09-03]. (原始內容存檔於2009-10-25).
- ^ PyQt v4.5 Released. Riverbank Computing Limited. 2009-06-05 [2011-04-28]. (原始內容存檔於2010-11-14).
- ^ Garbage Collection. [2013-06-24]. (原始內容存檔於2013-07-18).
延伸閱讀
- Summerfield, Mark, Rapid GUI Programming with Python and Qt(Covers PyQt4) 1st, Prentice Hall: 648, October 28, 2007 [2009-04-03], ISBN 978-0132354189, (原始內容存檔於2009-03-31)
- Rempt, Boudewijn, GUI Programming with Python: QT Edition(Covers PyQt3), OpenDocs, 2002 [2010-06-11], (原始內容存檔於2010-04-09)