- PyQt 教程
- PyQt - 首頁
- PyQt - 簡介
- PyQt - 環境搭建
- PyQt - Hello World
- PyQt - 主要類
- PyQt - 使用 Qt Designer
- PyQt - 元物件
- PyQt 訊號與槽
- PyQt - 訊號和槽
- PyQt - 支援和訊號
- PyQt - 未繫結和已繫結訊號
- PyQt - 使用 PyQtSignal 建立新的訊號
- PyQt - 連線、斷開和發射訊號
- PyQt - 槽裝飾器
- PyQt - 槽連線
- PyQt 佈局
- PyQt - 佈局管理
- PyQt - QBoxLayout
- PyQt - QGridLayout
- PyQt - QFormLayout
- PyQt - QHBoxLayout
- PyQt - QVBoxLayout
- PyQt - QStackedLayout
- PyQt - QGraphicsGridLayout
- PyQt - QGraphicsAnchorLayout
- PyQt - QGraphicsLayout
- PyQt - QGraphicsLinearLayout
- PyQt 基本控制元件
- PyQt - 基本控制元件
- PyQt - QLabel 控制元件
- PyQt - QLineEdit 控制元件
- PyQt - QPushButton 控制元件
- PyQt - QRadioButton 控制元件
- PyQt - QCheckBox 控制元件
- PyQt - QComboBox 控制元件
- PyQt - QSpinBox 控制元件
- PyQt - QMessageBox
- PyQt - QDialogButtonBox 控制元件
- PyQt - QFontComboBox 控制元件
- PyQt - QDoubleSpinBox 控制元件
- PyQt - QToolBox 控制元件
- PyQt - QDialog 類
- PyQt - QMessageBox
- PyQt - 多文件介面
- PyQt - 拖放
- PyQt 繪圖 API
- PyQt - 繪圖 API
- PyQt 資料庫
- PyQt - 資料庫操作
- PyQt 基礎
- PyQt - BrushStyle 常量
- PyQt - QClipboard
- PyQt - QPixmap 類
- PyQt 有用資源
- PyQt 快速指南
- PyQt - 有用資源
- PyQt - 討論
PyQt 快速指南
PyQt - 簡介
PyQt 是一個 GUI 控制元件工具包。它是 **Qt** 的 Python 介面,Qt 是一個最強大、最流行的跨平臺 GUI 庫之一。PyQt 由 RiverBank Computing Ltd. 開發。最新版本的 PyQt 可以從其官方網站下載 - riverbankcomputing.com
PyQt API 是一組包含大量類和函式的模組。**QtCore** 模組包含用於處理檔案和目錄等的非 GUI 功能,而 **QtGui** 模組包含所有圖形控制元件。此外,還有一些模組用於處理 XML **(QtXml)**、SVG **(QtSvg)** 和 SQL **(QtSql)** 等。
支援的環境
PyQt 相容所有流行的作業系統,包括 Windows、Linux 和 Mac OS。它採用雙重許可,可在 GPL 和商業許可下使用。
Windows
您可以從上面的下載連結下載並安裝相應的安裝程式,該安裝程式對應於 Python 版本 (2.7 或 3.4) 和硬體架構 (32 位或 64 位)。請注意,PyQt 有兩個版本可用,即 **PyQt 4.8** 和 **PyQt 5.5**。
PyQt4 可用於 Python 2 和 Python 3,而 PyQt5 只能與 Python 3.* 一起使用。
PyQt4 Windows 二進位制檔案
| PyQt4-4.11.4-gpl-Py3.4-Qt4.8.7-x64.exe | Windows 64 位安裝程式 |
| PyQt4-4.11.4-gpl-Py3.4-Qt4.8.7-x32.exe | Windows 32 位安裝程式 |
| PyQt4-4.11.4-gpl-Py3.4-Qt5.5.0-x64.exe | Windows 64 位安裝程式 |
| PyQt4-4.11.4-gpl-Py3.4-Qt5.5.0-x32.exe | Windows 32 位安裝程式 |
| PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x64.exe | Windows 64 位安裝程式 |
| PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x32.exe | Windows 32 位安裝程式 |
PyQt5 Windows 二進位制檔案
| PyQt5-5.5-gpl-Py3.4-Qt5.5.0-x64.exe | Windows 64 位安裝程式 |
| PyQt5-5.5-gpl-Py3.4-Qt5.5.0-x32.exe | Windows 32 位安裝程式 |
Linux
對於 Ubuntu 或任何其他 Debian Linux 發行版,使用以下命令安裝 PyQt:
sudo apt-get install python-qt4 or sudo apt-get install pyqt5-dev-tools
您也可以從“下載”頁面提供的原始碼進行構建。
| PyQt-x11-gpl-4.11.4.tar.gz | Linux、UNIX PyQt4 原始碼 |
| PyQt-gpl-5.5.tar.gz | Linux、UNIX、MacOS/X PyQt5 原始碼 |
Mac OS
PyQtX 專案 (http://sourceforge.net/projects/pyqtx/) 託管 PyQt 的 Mac 二進位制檔案。使用 Homebrew 安裝程式,按照以下命令:
brew install pyqt
PyQt - Hello World
使用 PyQt 建立簡單的 GUI 應用程式包含以下步驟:
匯入 QtGui 模組。
建立一個應用程式物件。
QWidget 物件建立一個頂級視窗。在其中新增 QLabel 物件。
將標籤的標題設定為“hello world”。
使用 setGeometry() 方法定義視窗的大小和位置。
使用 **app.exec_()** 方法進入應用程式的主迴圈。
import sys
from PyQt4 import QtGui
def window():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
b = QtGui.QLabel(w)
b.setText("Hello World!")
w.setGeometry(100,100,200,50)
b.move(50,20)
w.setWindowTitle(“PyQt”)
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
window()
以上程式碼產生以下輸出:
PyQt - 主要類
**PyQt API** 是一個大型的類和方法集合。這些類在 20 多個模組中定義。以下是經常使用的一些模組:
| 序號 | 模組和描述 |
|---|---|
| 1 |
QtCore 其他模組使用的核心非 GUI 類 |
| 2 |
QtGui 圖形使用者介面元件 |
| 3 |
QtMultimedia 用於低階多媒體程式設計的類 |
| 4 |
QtNetwork 用於網路程式設計的類 |
| 5 |
QtOpenGL OpenGL 支援類 |
| 6 |
QtScript 用於評估 Qt 指令碼的類 |
| 7 |
QtSql 使用 SQL 整合資料庫的類 |
| 8 |
QtSvg 用於顯示 SVG 檔案內容的類 |
| 9 |
QtWebKit 用於渲染和編輯 HTML 的類 |
| 10 |
QtXml 用於處理 XML 的類 |
| 11 |
QtAssistant 線上幫助支援 |
| 12 |
QtDesigner 用於擴充套件 Qt Designer 的類 |
PyQt API 包含 400 多個類。**QObject** 類位於類層次結構的頂部。它是所有 Qt 物件的基類。此外,**QPaintDevice** 類是所有可繪製物件的基類。
**QApplication** 類管理 GUI 應用程式的主要設定和控制流程。它包含主事件迴圈,在其中處理和分派由視窗元素和其他來源生成的事件。它還處理系統範圍和應用程式範圍的設定。
**QWidget** 類,派生自 QObject 和 QPaintDevice 類,是所有使用者介面物件的基類。**QDialog** 和 **QFrame** 類也派生自 QWidget 類。它們有自己的子類系統。
下圖描述了它們層次結構中的一些重要類。
這是一個經常使用的控制元件的選擇列表:
以下是常用控制元件。
| 序號 | 控制元件和描述 |
|---|---|
| 1 |
QLabel 用於顯示文字或影像 |
| 2 |
QLineEdit 允許使用者輸入一行文字 |
| 3 |
QTextEdit 允許使用者輸入多行文字 |
| 4 |
QPushButton 一個命令按鈕來呼叫操作 |
| 5 |
QRadioButton 允許從多個選項中選擇一個 |
| 6 |
QCheckBox 允許選擇多個選項 |
| 7 |
QSpinBox 允許增加/減少整數值 |
| 8 |
QScrollBar 允許訪問超出顯示區域的控制元件內容 |
| 9 |
QSlider 允許線性更改繫結值。 |
| 10 |
QComboBox 提供一個下拉列表供選擇 |
| 11 |
QMenuBar 包含 QMenu 物件的水平條 |
| 12 |
QStatusBar 通常位於 QMainWindow 的底部,提供狀態資訊。 |
| 13 |
QToolBar 通常位於 QMainWindow 的頂部或浮動。包含操作按鈕 |
| 14 |
QListView 以列表模式或圖示模式提供可選擇的專案列表 |
| 15 |
QPixmap 用於在 QLabel 或 QPushButton 物件上顯示的螢幕外影像表示 |
| 16 |
QDialog 模態或非模態視窗,可以向父視窗返回資訊 |
典型的基於 GUI 的應用程式的頂級視窗由 **QMainWindow** 控制元件物件建立。上面列出的一些控制元件佔據其指定位置在這個主視窗中,而其他控制元件則使用各種佈局管理器放置在中央控制元件區域。
下圖顯示了 QMainWindow 框架:
PyQt - 使用 Qt Designer
PyQt 安裝程式帶有一個名為 **Qt Designer** 的 GUI 構建器工具。使用其簡單的拖放介面,可以快速構建 GUI 介面,而無需編寫程式碼。然而,它不是像 Visual Studio 這樣的 IDE。因此,Qt Designer 沒有除錯和構建應用程式的功能。
使用 Qt Designer 建立 GUI 介面首先要為應用程式選擇一個頂級視窗。
然後,您可以將所需的控制元件從左側窗格的控制元件框中拖放到表單上。您還可以為表單上控制元件的屬性賦值。
設計的表單將儲存為 demo.ui。此 ui 檔案包含設計中控制元件及其屬性的 XML 表示。此設計透過使用 pyuic4 命令列實用程式轉換為 Python 等效項。此實用程式是 uic 模組的包裝器。pyuic4 的用法如下:
pyuic4 –x demo.ui –o demo.py
在上述命令中,-x 開關會向生成的 XML 新增少量附加程式碼,使其成為一個自執行的獨立應用程式。
if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) Dialog = QtGui.QDialog() ui = Ui_Dialog() ui.setupUi(Dialog) Dialog.show() sys.exit(app.exec_())
執行生成的 Python 指令碼將顯示以下對話方塊:
使用者可以在輸入欄位中輸入資料,但單擊“新增”按鈕不會生成任何操作,因為它沒有與任何函式關聯。對使用者生成的響應做出反應稱為 **事件處理**。
PyQt - 訊號與槽
與以順序方式執行的控制檯模式應用程式不同,基於 GUI 的應用程式是事件驅動的。函式或方法是響應使用者操作(例如單擊按鈕、從集合中選擇專案或滑鼠單擊等,稱為 **事件**)而執行的。
用於構建 GUI 介面的控制元件充當此類事件的來源。每個從 QObject 類派生的 PyQt 控制元件都設計為響應一個或多個事件而發出“**訊號**”。訊號本身不會執行任何操作。相反,它連線到“**槽**”。槽可以是任何 **可呼叫的 Python 函式**。
在 PyQt 中,訊號和槽之間的連線可以透過不同的方式實現。以下是最常用的技術:
QtCore.QObject.connect(widget, QtCore.SIGNAL(‘signalname’), slot_function)
當控制元件發出訊號時,呼叫 slot_function 的更方便的方法如下:
widget.signal.connect(slot_function)
假設需要在單擊按鈕時呼叫一個函式。這裡,單擊訊號需要連線到一個可呼叫的函式。這可以透過以下兩種技術中的任何一種實現:
QtCore.QObject.connect(button, QtCore.SIGNAL(“clicked()”), slot_function)
或
button.clicked.connect(slot_function)
示例
在下面的示例中,兩個 QPushButton 物件 (b1 和 b2) 被新增到 QDialog 視窗中。我們希望分別在單擊 b1 和 b2 時呼叫函式 b1_clicked() 和 b2_clicked()。
單擊 b1 時,clicked() 訊號連線到 b1_clicked() 函式
b1.clicked.connect(b1_clicked())
單擊 b2 時,clicked() 訊號連線到 b2_clicked() 函式
QObject.connect(b2, SIGNAL("clicked()"), b2_clicked)
示例
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def window():
app = QApplication(sys.argv)
win = QDialog()
b1 = QPushButton(win)
b1.setText("Button1")
b1.move(50,20)
b1.clicked.connect(b1_clicked)
b2 = QPushButton(win)
b2.setText("Button2")
b2.move(50,50)
QObject.connect(b2,SIGNAL("clicked()"),b2_clicked)
win.setGeometry(100,100,200,100)
win.setWindowTitle("PyQt")
win.show()
sys.exit(app.exec_())
def b1_clicked():
print "Button 1 clicked"
def b2_clicked():
print "Button 2 clicked"
if __name__ == '__main__':
window()
以上程式碼產生以下輸出:
輸出
Button 1 clicked Button 2 clicked
PyQt - 佈局管理
可以透過指定其以畫素為單位測量的絕對座標,將 GUI 小部件放置在容器視窗內。座標相對於 `setGeometry()` 方法定義的視窗尺寸。
`setGeometry()` 語法
QWidget.setGeometry(xpos, ypos, width, height)
在下面的程式碼片段中,將顯示一個 300 x 200 畫素的頂級視窗,顯示在監視器的 (10, 10) 位置。
import sys
from PyQt4 import QtGui
def window():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
b = QtGui.QPushButton(w)
b.setText("Hello World!")
b.move(50,20)
w.setGeometry(10,10,300,200)
w.setWindowTitle(“PyQt”)
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
window()
一個 **PushButton** 小部件新增到視窗中,並放置在視窗左上角位置右側 50 畫素,下方 20 畫素的位置。
然而,這種 **絕對定位** 由於以下原因並不適用:
即使調整視窗大小,小部件的位置也不會改變。
在具有不同解析度的不同顯示裝置上,外觀可能不一致。
佈局修改很困難,因為它可能需要重新設計整個表單。
PyQt API 提供了佈局類,用於更優雅地管理容器內小部件的位置。佈局管理器相對於絕對定位的優點是:
視窗內的小部件會自動調整大小。
確保在具有不同解析度的顯示裝置上外觀一致。
可以動態新增或刪除小部件,而無需重新設計。
以下是我們將在本章中逐一討論的類列表。
| 序號 | 類與說明 |
|---|---|
| 1 | QBoxLayout
QBoxLayout 類垂直或水平排列小部件。其派生類是 QVBoxLayout(用於垂直排列小部件)和 QHBoxLayout(用於水平排列小部件)。 |
| 2 | QGridLayout
GridLayout 類物件以網格形式呈現,單元格按行和列排列。該類包含 addWidget() 方法。可以透過指定單元格的行數和列數來新增任何小部件。 |
| 3 | QFormLayout
QFormLayout 是一種建立兩列表單的便捷方法,其中每一行都包含一個與標籤關聯的輸入欄位。按照慣例,左列包含標籤,右列包含輸入欄位。 |
PyQt - 基本控制元件
以下是我們將在本章中逐一討論的小部件列表。
| 序號 | 控制元件和描述 |
|---|---|
| 1 | QLabel
QLabel 物件充當佔位符,用於顯示不可編輯的文字或影像,或動畫 GIF 電影。它也可以用作其他小部件的助記鍵。 |
| 2 | QLineEdit
QLineEdit 物件是最常用的輸入欄位。它提供一個框,可以在其中輸入一行文字。為了輸入多行文字,需要 QTextEdit 物件。 |
| 3 | QPushButton
在 PyQt API 中,QPushButton 類物件顯示一個按鈕,單擊該按鈕可以程式設計為呼叫某個函式。 |
| 4 | QRadioButton
QRadioButton 類物件顯示一個帶有文字標籤的可選擇按鈕。使用者可以選擇表單上呈現的多個選項之一。此類派生自 QAbstractButton 類。 |
| 5 | QCheckBox
當將 QCheckBox 物件新增到父視窗時,文字標籤前面會出現一個矩形框。與 QRadioButton 一樣,它也是一個可選擇按鈕。 |
| 6 | QComboBox
QComboBox 物件顯示一個下拉列表,從中選擇專案。它在表單上佔據最小的螢幕空間,只需顯示當前選定的專案。 |
| 7 | QSpinBox
QSpinBox 物件為使用者提供一個文字框,該文字框顯示一個整數,其右側帶有向上/向下按鈕。 |
| 8 | QSlider 小部件和訊號
QSlider 類物件為使用者提供一個凹槽,可以在其上移動手柄。它是控制有界值的經典小部件。 |
| 9 | QMenuBar、QMenu 和 QAction
QMainWindow 物件標題欄正下方的水平 QMenuBar 用於顯示 QMenu 物件。 |
| 10 | QToolBar
QToolBar 小部件是一個可移動的面板,由文字按鈕、帶圖示的按鈕或其他小部件組成。 |
| 11 | QInputDialog
這是一個預配置的對話方塊,帶有文字欄位和兩個按鈕“確定”和“取消”。在使用者單擊“確定”按鈕或按 Enter 鍵後,父視窗收集文字框中的輸入。 |
| 12 | QFontDialog
另一個常用的對話方塊,字型選擇器小部件是 QDialog 類的視覺外觀。此對話方塊的結果是一個 Qfont 物件,父視窗可以使用該物件。 |
| 13 | QFileDialog
此小部件是一個檔案選擇器對話方塊。它使使用者能夠瀏覽檔案系統並選擇要開啟或儲存的檔案。可以透過靜態函式或在對話方塊物件上呼叫 exec_() 函式來呼叫該對話方塊。 |
| 14 | QTab
如果表單的欄位過多,無法同時顯示,則可以將它們排列在選項卡式小部件每個選項卡下放置的不同頁面中。QTabWidget 提供了一個選項卡欄和一個頁面區域。 |
| 15 | QStacked
QStackedWidget 的功能類似於 QTabWidget。它還有助於有效利用視窗的客戶區。 |
| 16 | QSplitter
如果表單的欄位過多,無法同時顯示,則可以將它們排列在選項卡式小部件每個選項卡下放置的不同頁面中。QTabWidget 提供了一個選項卡欄和一個頁面區域。 |
| 17 | QDock
可停靠視窗是可以保持浮動狀態或可以附加到主視窗指定位置的子視窗。QMainWindow 類的主視窗物件有一個為可停靠視窗保留的區域。 |
| 18 | QStatusBar
QMainWindow 物件在底部保留一個水平欄作為狀態列。它用於顯示永久性或上下文狀態資訊。 |
| 19 | QList
QListWidget 類是一個基於專案的介面,用於向列表新增或從中刪除專案。列表中的每個專案都是一個 QListWidgetItem 物件。ListWidget 可以設定為多選。 |
| 20 | QScrollBar
捲軸控制元件使使用者能夠訪問不在可視區域內的文件部分。它提供當前位置的視覺指示器。 |
| 21 | QCalendar
QCalendar 小部件是一個有用的日期選擇器控制元件。它提供基於月份的檢視。使用者可以使用滑鼠或鍵盤選擇日期,預設日期為今天的日期。 |
PyQt - QDialog 類
**QDialog** 小部件顯示一個頂級視窗,主要用於收集使用者的響應。它可以配置為 **模態**(阻止其父視窗)或 **非模態**(可以繞過對話方塊視窗)。
PyQt API 有一些預配置的對話方塊小部件,例如 InputDialog、FileDialog、FontDialog 等。
示例
在下面的示例中,對話方塊視窗的 WindowModality 屬性決定它是模態還是非模態。可以將對話方塊上的任何一個按鈕設定為預設按鈕。當用戶按下 Escape 鍵時,QDialog.reject() 方法將丟棄對話方塊。
頂級 QWidget 視窗上的 PushButton 單擊時會生成一個對話方塊視窗。對話方塊框在其標題欄上沒有最小化和最大化控制元件。
使用者無法將此對話方塊框置於後臺,因為其 WindowModality 設定為 ApplicationModal。
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
def window():
app = QApplication(sys.argv)
w = QWidget()
b = QPushButton(w)
b.setText("Hello World!")
b.move(50,50)
b.clicked.connect(showdialog)
w.setWindowTitle("PyQt Dialog demo")
w.show()
sys.exit(app.exec_())
def showdialog():
d = QDialog()
b1 = QPushButton("ok",d)
b1.move(50,50)
d.setWindowTitle("Dialog")
d.setWindowModality(Qt.ApplicationModal)
d.exec_()
if __name__ == '__main__':
window()
以上程式碼產生以下輸出:
PyQt - QMessageBox
**QMessageBox** 是一個常用的模態對話方塊,用於顯示一些資訊訊息,並可以選擇要求使用者透過單擊其上的任何一個標準按鈕來響應。每個標準按鈕都有一個預定義的標題、一個角色並返回一個預定義的十六進位制數字。
與 QMessageBox 類關聯的重要方法和列舉在下面的表格中給出:
| 序號 | 方法與說明 |
|---|---|
| 1 |
setIcon() 顯示與訊息嚴重性相對應的預定義圖示
|
| 2 |
setText() 設定要顯示的主要訊息文字 |
| 3 |
setInformativeText() 顯示附加資訊 |
| 4 |
setDetailText() 對話方塊顯示“詳細資訊”按鈕。單擊此按鈕時會出現此文字 |
| 5 |
setTitle() 顯示對話方塊的自定義標題 |
| 6 |
setStandardButtons() 要顯示的標準按鈕列表。每個按鈕都與 QMessageBox.Ok 0x00000400 QMessageBox.Open 0x00002000 QMessageBox.Save 0x00000800 QMessageBox.Cancel 0x00400000 QMessageBox.Close 0x00200000 QMessageBox.Yes 0x00004000 QMessageBox.No 0x00010000 QMessageBox.Abort 0x00040000 QMessageBox.Retry 0x00080000 QMessageBox.Ignore 0x00100000 |
| 7 |
setDefaultButton() 將按鈕設定為預設按鈕。如果按下 Enter 鍵,它會發出 clicked 訊號 |
| 8 |
setEscapeButton() 將按鈕設定為在按下 Escape 鍵時視為已單擊 |
示例
在下面的示例中,頂級視窗上按鈕的單擊訊號,連線的函式顯示訊息框對話方塊。
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("This is a message box")
msg.setInformativeText("This is additional information")
msg.setWindowTitle("MessageBox demo")
msg.setDetailedText("The details are as follows:")
setStandardButton() 函式顯示所需的按鈕。
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
buttonClicked() 訊號連線到一個槽函式,該函式標識訊號源的標題。
msg.buttonClicked.connect(msgbtn)
示例的完整程式碼如下:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
def window():
app = QApplication(sys.argv)
w = QWidget()
b = QPushButton(w)
b.setText("Show message!")
b.move(50,50)
b.clicked.connect(showdialog)
w.setWindowTitle("PyQt Dialog demo")
w.show()
sys.exit(app.exec_())
def showdialog():
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("This is a message box")
msg.setInformativeText("This is additional information")
msg.setWindowTitle("MessageBox demo")
msg.setDetailedText("The details are as follows:")
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
msg.buttonClicked.connect(msgbtn)
retval = msg.exec_()
print "value of pressed message box button:", retval
def msgbtn(i):
print "Button pressed is:",i.text()
if __name__ == '__main__':
window()
以上程式碼產生以下輸出:
PyQt - 多文件介面
典型的 GUI 應用程式可能有多個視窗。選項卡式和小部件允許一次啟用一個這樣的視窗。但是,很多時候這種方法可能並不實用,因為其他視窗的檢視被隱藏了。
同時顯示多個視窗的一種方法是將它們建立為獨立視窗。這稱為 SDI(單文件介面)。這需要更多的記憶體資源,因為每個視窗可能都有自己的菜單系統、工具欄等。
MDI(多文件介面)應用程式消耗的記憶體資源更少。子視窗相對於彼此放置在主容器內。容器小部件稱為 **QMdiArea**。
QMdiArea 小部件通常佔據 QMainWondow 物件的中央小部件。此區域中的子視窗是 QMdiSubWindow 類的例項。可以將任何 QWidget 設定為 subWindow 物件的內部小部件。MDI 區域中的子視窗可以以級聯或平鋪方式排列。
下表列出了 QMdiArea 類和 QMdiSubWindow 類的重要方法:
| 序號 | 方法與說明 |
|---|---|
| 1 |
addSubWindow() 將小部件作為新子視窗新增到 MDI 區域 |
| 2 |
removeSubWindow() 刪除作為子視窗內部小部件的小部件 |
| 3 |
setActiveSubWindow() 啟用子視窗 |
| 4 |
cascadeSubWindows() 以級聯方式排列 MDiArea 中的子視窗 |
| 5 |
tileSubWindows() 以平鋪方式排列 MDiArea 中的子視窗 |
| 6 |
closeActiveSubWindow() 關閉活動子視窗 |
| 7 |
subWindowList() 返回 MDI 區域中的子視窗列表 |
| 8 |
setWidget() 將一個 QWidget 設定為 QMdiSubwindow 例項的內部部件 |
QMdiArea 物件發出 subWindowActivated() 訊號,而 windowStateChanged() 訊號由 QMdiSubWindow 物件發出。
示例
在下面的示例中,頂級視窗包含 QMainWindow,其中包含選單和 MdiArea。
self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar = self.menuBar()
file = bar.addMenu("File")
file.addAction("New")
file.addAction("cascade")
file.addAction("Tiled")
選單的 triggered() 訊號連線到 windowaction() 函式。
file.triggered[QAction].connect(self.windowaction)
選單的新操作在 MDI 區域中新增一個子視窗,標題中包含一個遞增的數字。
MainWindow.count = MainWindow.count+1
sub = QMdiSubWindow()
sub.setWidget(QTextEdit())
sub.setWindowTitle("subwindow"+str(MainWindow.count))
self.mdi.addSubWindow(sub)
sub.show()
選單的“層疊”和“平鋪”按鈕分別以層疊和平鋪的方式排列當前顯示的子視窗。
完整的程式碼如下:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MainWindow(QMainWindow):
count = 0
def __init__(self, parent = None):
super(MainWindow, self).__init__(parent)
self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar = self.menuBar()
file = bar.addMenu("File")
file.addAction("New")
file.addAction("cascade")
file.addAction("Tiled")
file.triggered[QAction].connect(self.windowaction)
self.setWindowTitle("MDI demo")
def windowaction(self, q):
print "triggered"
if q.text() == "New":
MainWindow.count = MainWindow.count+1
sub = QMdiSubWindow()
sub.setWidget(QTextEdit())
sub.setWindowTitle("subwindow"+str(MainWindow.count))
self.mdi.addSubWindow(sub)
sub.show()
if q.text() == "cascade":
self.mdi.cascadeSubWindows()
if q.text() == "Tiled":
self.mdi.tileSubWindows()
def main():
app = QApplication(sys.argv)
ex = MainWindow()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
以上程式碼產生以下輸出:
PyQt - 拖放
拖放功能對於使用者來說非常直觀。它存在於許多桌面應用程式中,使用者可以在這些應用程式中將物件從一個視窗複製或移動到另一個視窗。
基於 MIME 的拖放資料傳輸基於 QDrag 類。QMimeData 物件將其資料與其對應的 MIME 型別關聯。它儲存在剪貼簿中,然後用於拖放過程。
以下 QMimeData 類函式允許方便地檢測和使用 MIME 型別。
| 測試器 | 獲取器 | 設定器 | MIME 型別 |
|---|---|---|---|
| hasText() | text() | setText() | text/plain |
| hasHtml() | html() | setHtml() | text/html |
| hasUrls() | urls() | setUrls() | text/uri-list |
| hasImage() | imageData() | setImageData() | image/* |
| hasColor() | colorData() | setColorData() | application/x-color |
許多 QWidget 物件支援拖放操作。允許拖動其資料的那些物件已設定 setDragEnabled(),必須將其設定為 true。另一方面,視窗部件應該響應拖放事件以便儲存拖放到其中的資料。
DragEnterEvent 提供一個事件,該事件在拖動操作進入目標視窗部件時傳送到目標視窗部件。
DragMoveEvent 用於拖放操作正在進行時。
DragLeaveEvent 在拖放操作離開視窗部件時生成。
另一方面,DropEvent 在放下操作完成後發生。可以有條件地接受或拒絕事件的建議操作。
示例
在以下程式碼中,DragEnterEvent 驗證事件的 MIME 資料是否包含文字。如果是,則接受事件的建議操作,並將文字作為新專案新增到 ComboBox 中。
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class combo(QComboBox):
def __init__(self, title, parent):
super(combo, self).__init__( parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e):
print e
if e.mimeData().hasText():
e.accept()
else:
e.ignore()
def dropEvent(self, e):
self.addItem(e.mimeData().text())
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
lo = QFormLayout()
lo.addRow(QLabel("Type some text in textbox and drag it into combo box"))
edit = QLineEdit()
edit.setDragEnabled(True)
com = combo("Button", self)
lo.addRow(edit,com)
self.setLayout(lo)
self.setWindowTitle('Simple drag & drop')
def main():
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
if __name__ == '__main__':
main()
以上程式碼產生以下輸出:
PyQt - 資料庫操作
PyQt API 包含一個詳盡的類系統,用於與許多基於 SQL 的資料庫進行通訊。它的 QSqlDatabase 透過 Connection 物件提供訪問。以下是當前可用的 SQL 驅動程式列表:
| 序號 | 驅動程式型別和描述 |
|---|---|
| 1 | QDB2 IBM DB2 |
| 2 | QIBASE Borland InterBase 驅動程式 |
| 3 | QMYSQL MySQL 驅動程式 |
| 4 | QOCI Oracle 呼叫介面驅動程式 |
| 5 | QODBC ODBC 驅動程式(包括 Microsoft SQL Server) |
| 6 | QPSQL PostgreSQL 驅動程式 |
| 7 | QSQLITE SQLite 3 版或更高版本 |
| 8 | QSQLITE2 SQLite 2 版 |
示例
使用靜態方法建立與 SQLite 資料庫的連線:
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('sports.db')
QSqlDatabase 類的其他方法如下:
| 序號 | 方法與說明 |
|---|---|
| 1 |
setDatabaseName() 設定要與其建立連線的資料庫的名稱 |
| 2 |
setHostName() 設定安裝資料庫的主機的名稱 |
| 3 |
setUserName() 指定連線的使用者名稱 |
| 4 |
setPassword() 設定連線物件的密碼(如有) |
| 5 |
commit() 提交事務,如果成功則返回 true |
| 6 |
rollback() 回滾資料庫事務 |
| 7 |
close() 關閉連線 |
QSqlQuery 類具有執行和操作 SQL 命令的功能。可以執行 DDL 和 DML 型別的 SQL 查詢。該類中最重要的函式是 exec_(),它接受一個包含要執行的 SQL 語句的字串作為引數。
query = QtSql.QSqlQuery()
query.exec_("create table sportsmen(id int primary key,
" "firstname varchar(20), lastname varchar(20))")
以下指令碼建立一個 SQLite 資料庫 sports.db,其中包含一個填充了五個記錄的運動員表。
from PyQt4 import QtSql, QtGui
def createDB():
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('sports.db')
if not db.open():
QtGui.QMessageBox.critical(None, QtGui.qApp.tr("Cannot open database"),
QtGui.qApp.tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information "
"how to build it.\n\n" "Click Cancel to exit."),
QtGui.QMessageBox.Cancel)
return False
query = QtSql.QSqlQuery()
query.exec_("create table sportsmen(id int primary key, "
"firstname varchar(20), lastname varchar(20))")
query.exec_("insert into sportsmen values(101, 'Roger', 'Federer')")
query.exec_("insert into sportsmen values(102, 'Christiano', 'Ronaldo')")
query.exec_("insert into sportsmen values(103, 'Ussain', 'Bolt')")
query.exec_("insert into sportsmen values(104, 'Sachin', 'Tendulkar')")
query.exec_("insert into sportsmen values(105, 'Saina', 'Nehwal')")
return True
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
createDB()
PyQt 中的 QSqlTableModel 類是一個高階介面,它提供可編輯的資料模型,用於讀取和寫入單個表中的記錄。此模型用於填充 QTableView 物件。它為使用者提供了一個可滾動和可編輯的檢視,可以將其放在任何頂級視窗上。
QTableModel 物件的宣告方式如下:
model = QtSql.QSqlTableModel()
其編輯策略可以設定為以下任何一種:
| QSqlTableModel.OnFieldChange | 所有更改將立即應用 |
| QSqlTableModel.OnRowChange | 更改將在使用者選擇不同的行時應用 |
| QSqlTableModel.OnManualSubmit | 所有更改都將快取,直到呼叫 submitAll() 或 revertAll() 為止 |
示例
在以下示例中,sportsperson 表用作模型,策略設定為:
model.setTable('sportsmen')
model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
model.select()
QTableView 類是 PyQt 中 Model/View 框架的一部分。QTableView 物件的建立方式如下:
view = QtGui.QTableView() view.setModel(model) view.setWindowTitle(title) return view
此 QTableView 物件和兩個 QPushButton 視窗部件新增到頂級 QDialog 視窗中。新增按鈕的 clicked() 訊號連線到 addrow(),後者在模型表上執行 insertRow()。
button.clicked.connect(addrow) def addrow(): print model.rowCount() ret = model.insertRows(model.rowCount(), 1) print ret
與刪除按鈕關聯的槽執行一個 lambda 函式,該函式刪除使用者選擇的行。
btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row()))
完整的程式碼如下:
import sys
from PyQt4 import QtCore, QtGui, QtSql
import sportsconnection
def initializeModel(model):
model.setTable('sportsmen')
model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
model.select()
model.setHeaderData(0, QtCore.Qt.Horizontal, "ID")
model.setHeaderData(1, QtCore.Qt.Horizontal, "First name")
model.setHeaderData(2, QtCore.Qt.Horizontal, "Last name")
def createView(title, model):
view = QtGui.QTableView()
view.setModel(model)
view.setWindowTitle(title)
return view
def addrow():
print model.rowCount()
ret = model.insertRows(model.rowCount(), 1)
print ret
def findrow(i):
delrow = i.row()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('sports.db')
model = QtSql.QSqlTableModel()
delrow = -1
initializeModel(model)
view1 = createView("Table Model (View 1)", model)
view1.clicked.connect(findrow)
dlg = QtGui.QDialog()
layout = QtGui.QVBoxLayout()
layout.addWidget(view1)
button = QtGui.QPushButton("Add a row")
button.clicked.connect(addrow)
layout.addWidget(button)
btn1 = QtGui.QPushButton("del a row")
btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row()))
layout.addWidget(btn1)
dlg.setLayout(layout)
dlg.setWindowTitle("Database Demo")
dlg.show()
sys.exit(app.exec_())
以上程式碼產生以下輸出:
PyQt - 繪圖 API
PyQt 中的所有QWidget類都是從QPaintDevice類派生的。QPaintDevice是對二維空間的抽象,可以使用QPainter在其上繪製。繪圖裝置的尺寸以畫素為單位測量,從左上角開始。
QPainter 類在視窗部件和其他可繪製裝置(如印表機)上執行低階繪圖。通常,它用於視窗部件的繪製事件。每當視窗部件的外觀更新時,就會發生QPaintEvent。
透過呼叫 begin() 方法啟用畫家,而 end() 方法停用它。在這兩者之間,透過以下表格中列出的合適方法繪製所需的圖案。
| 序號 | 方法與說明 |
|---|---|
| 1 |
begin() 開始在目標裝置上繪製 |
| 2 |
drawArc() 繪製起始角度和結束角度之間的弧線 |
| 3 |
drawEllipse() 在矩形內繪製橢圓 |
| 4 |
drawLine() 繪製一條指定端點座標的線 |
| 5 |
drawPixmap() 從影像檔案中提取 pixmap 並將其顯示在指定位置 |
| 6 |
drawPolygon() 使用座標陣列繪製多邊形 |
| 7 |
drawRect() 從左上角座標開始繪製具有給定寬度和高度的矩形 |
| 8 |
drawText() 在給定座標處顯示文字 |
| 9 |
fillRect() 用 QColor 引數填充矩形 |
| 10 |
setBrush() 設定繪圖的畫筆樣式 |
| 11 |
setPen() 設定用於繪圖的筆的顏色、大小和樣式 |
PyQt - BrushStyle 常量
預定義的 QColor 樣式
| Qt.NoBrush | 無畫筆圖案 |
| Qt.SolidPattern | 均勻顏色 |
| Qt.Dense1Pattern | 極其密集的畫筆圖案 |
| Qt.HorPattern | 水平線 |
| Qt.VerPattern | 垂直線 |
| Qt.CrossPattern | 交叉的水平線和垂直線 |
| Qt.BDiagPattern | 向後對角線 |
| Qt.FDiagPattern | 向前對角線 |
| Qt.DiagCrossPattern | 交叉對角線 |
預定義的 QColor 物件
| Qt.white |
| Qt.black |
| Qt.red |
| Qt.darkRed |
| Qt.green |
| Qt.darkGreen |
| Qt.blue |
| Qt.cyan |
| Qt.magenta |
| Qt.yellow |
| Qt.darkYellow |
| Qt.gray |
可以透過指定 RGB 或 CMYK 或 HSV 值來選擇自定義顏色。
示例
以下示例實現其中一些方法。
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.text = "hello world"
self.setGeometry(100,100, 400,300)
self.setWindowTitle('Draw Demo')
self.show()
def paintEvent(self, event):
qp = QPainter()
qp.begin(self)
qp.setPen(QColor(Qt.red))
qp.setFont(QFont('Arial', 20))
qp.drawText(10,50, "hello Pyth
on")
qp.setPen(QColor(Qt.blue))
qp.drawLine(10,100,100,100)
qp.drawRect(10,150,150,100)
qp.setPen(QColor(Qt.yellow))
qp.drawEllipse(100,50,100,50)
qp.drawPixmap(220,10,QPixmap("python.jpg"))
qp.fillRect(200,175,150,100,QBrush(Qt.SolidPattern))
qp.end()
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
以上程式碼產生以下輸出:
PyQt - QClipboard
QClipboard 類提供對系統範圍的剪貼簿的訪問,該剪貼簿提供了一種簡單的機制,可以在應用程式之間複製和貼上資料。其作用類似於 QDrag 類,並使用類似的資料型別。
QApplication 類具有一個靜態方法 clipboard(),它返回對剪貼簿物件的引用。任何型別的 MimeData 都可以複製到剪貼簿或從剪貼簿貼上。
以下是常用剪貼簿類方法:
| 序號 | 方法與說明 |
|---|---|
| 1 |
clear() 清除剪貼簿內容 |
| 2 |
setImage() 將 QImage 複製到剪貼簿 |
| 3 |
setMimeData() 將 MIME 資料設定為剪貼簿 |
| 4 |
setPixmap() 將 Pixmap 物件複製到剪貼簿 |
| 5 |
setText() 將 QString 複製到剪貼簿 |
| 6 |
text() 從剪貼簿檢索文字 |
與剪貼簿物件關聯的訊號為:
| 序號 | 方法和描述 |
|---|---|
| 1 |
dataChanged() 每當剪貼簿資料更改時 |
示例
在以下示例中,兩個 TextEdit 物件和兩個 PushButtons 新增到頂級視窗。
首先例項化剪貼簿物件。textedit 物件的 copy() 方法將資料複製到系統剪貼簿。單擊“貼上”按鈕時,它會獲取剪貼簿資料並將其貼上到另一個 textedit 物件中。
PyQt - QPixmap 類
QPixmap 類提供影像的螢幕外表示。它可以用作 QPaintDevice 物件,也可以載入到另一個視窗部件中,通常是標籤或按鈕。
Qt API 還有另一個類似的類 QImage,它針對 I/O 和其他畫素操作進行了最佳化。另一方面,Pixmap 針對在螢幕上顯示進行了最佳化。這兩種格式都是可相互轉換的。
可以讀取到 QPixmap 物件中的影像檔案型別如下:
| BMP | Windows 點陣圖 |
| GIF | 圖形交換格式(可選) |
| JPG | 聯合影像專家組 |
| JPEG | 聯合影像專家組 |
| PNG | 行動式網路圖形 |
| PBM | 行動式點陣圖 |
| PGM | 行動式灰度圖 |
| PPM | 行動式畫素圖 |
| XBM | X11 點陣圖 |
| XPM | X11 畫素圖 |
以下方法可用於處理 QPixmap 物件:
| 序號 | 方法與說明 |
|---|---|
| 1 |
copy() 從 QRect 物件複製 pixmap 資料 |
| 2 |
fromImage() 將 QImage 物件轉換為 QPixmap |
| 3 |
grabWidget() 從給定視窗部件建立 pixmap |
| 4 |
grabWindow() 建立視窗中資料的 pixmap |
| 5 |
load() 將影像檔案載入為 pixmap |
| 6 |
save() 將 QPixmap 物件儲存為檔案 |
| 7 |
toImage() 將 QPixmap 轉換為 QImage |
QPixmap 最常見的用途是在標籤/按鈕上顯示影像。
示例
以下示例顯示使用 setPixmap() 方法在 QLabel 上顯示的影像。完整的程式碼如下:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def window():
app = QApplication(sys.argv)
win = QWidget()
l1 = QLabel()
l1.setPixmap(QPixmap("python.jpg"))
vbox = QVBoxLayout()
vbox.addWidget(l1)
win.setLayout(vbox)
win.setWindowTitle("QPixmap Demo")
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
window()
以上程式碼產生以下輸出:
疑問
資訊
警告
嚴重錯誤