程式語言:Python
Package:PyQt5
官網
官網文件
功能:建立 GUI 人機介面
範例
簡單視窗
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
-
-
- if __name__ == '__main__':
- # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
- app = QApplication(sys.argv)
-
- # 建立 QWidget
- w = QWidget()
- # 設定尺寸
- w.resize(250, 150)
- # 設定位置
- w.move(300, 300)
- # 設定標題
- w.setWindowTitle('Simple')
- # 顯示,因圖形元件被創造時都是 hidden 狀態
- w.show()
-
- # app.exec_() 讓 QApplication 進入 event loop
- # exec 是 Python keyword,所以會多出底線
- sys.exit(app.exec_())
簡單按鈕
- import sys
- from PyQt5.QtWidgets import QApplication, QPushButton
-
-
- if __name__ == '__main__':
- # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
- app = QApplication(sys.argv)
-
- # & + 字元,可設定快捷鍵 Alt + E
- # Qt 設定 action focus 的簡便方法
- button = QPushButton("H&ello!")
- # 設定尺寸
- button.resize(200, 75)
- # 設定位置
- button.move(500, 400)
- # 設定視窗標題
- button.setWindowTitle("Hello World")
- # 顯示,因圖形元件被創造時都是 hidden 狀態
- button.show()
-
- # app.exec_() 讓 QApplication 進入 event loop
- # exec 是 Python keyword,所以會多出底線
- sys.exit(app.exec_())
簡單排版
- 由上到下的概念
- 通常只需要一個 top-level window,也就是 parent 為 None
- top-level window 擁有標題列和邊框
- 每個 widget 可有其所屬的 parent ( 預設參數 parent=None )
- 當 parent 解構時,child 們也會一同解構
- 如何成為 parent
- 當 A 調用 addWidget(w),A 就會成為 w 的 parent
- 當 A 調用 setLayout(layout) ,A 就會成為 layout 的 parent,並接管 layout 的所有 child
- 不只這些,不同物件有不同的 function
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
-
-
- if __name__ == '__main__':
- # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
- app = QApplication(sys.argv)
-
- # & + 字元,可設定快捷鍵 Alt + E
- # Qt 設定 action focus 的簡便方法
- ok = QPushButton("&OK")
- cancel = QPushButton("&Cancel")
-
- # 基本排版元件,有 QHBoxLayout() & QVBoxLayout()
- layout = QHBoxLayout()
- # 加入 ok button 並設為 child
- layout.addWidget(ok)
- # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
- # 數量可設定,增加彈力
- layout.addStretch(1)
- # 加入 cancel button 並設為 child
- layout.addWidget(cancel)
- # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
- # 數量可設定,增加彈力
- layout.addStretch(2)
-
- # 建立 widget 元件,並為 top-level window
- widget = QWidget()
- # 設定 layout 元件,並設為 child
- widget.setLayout(layout)
- # 顯示,因圖形元件被創造時都是 hidden 狀態
- widget.show()
-
- # app.exec_() 讓 QApplication 進入 event loop
- # exec 是 Python keyword,所以會多出底線
- sys.exit(app.exec_())
簡單 Signals & Slots 範例
- 多 singals 對 多 slots
- slots 可為任意 function
- 參數可為 Python 任意型態
- signal 與 signal 可互相連接,產生連鎖反應
- 可 connect,也可 disconnect
- import sys
- from PyQt5.QtCore import Qt
- from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QSpinBox, QSlider, QMessageBox
-
- def helloWorld():
- QMessageBox.information(None, 'Message', 'Hello World', QMessageBox.Ok)
-
- if __name__ == '__main__':
- # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
- app = QApplication(sys.argv)
-
- # & + 字元,可設定快捷鍵 Alt + E
- # Qt 設定 action focus 的簡便方法
- button = QPushButton("H&ello!")
-
- # 建立 QSpinBox
- spinBox = QSpinBox()
- # 設定前罝符號
- spinBox.setPrefix("$")
- # 設定範圍
- spinBox.setRange(0, 100)
-
- # 建立橫向 QSlider
- slider = QSlider(Qt.Horizontal)
- # 設定範圍
- slider.setRange(0, 100)
-
- # signals 連接 slots
- button.clicked.connect(helloWorld)
- spinBox.valueChanged.connect(slider.setValue)
- slider.valueChanged.connect(spinBox.setValue)
-
- # 基本排版元件,有 QHBoxLayout() & QVBoxLayout()
- layout = QHBoxLayout()
- # 加入 ok button 並設為 child
- layout.addWidget(button)
- # 加入 spinBox 並設為 child
- layout.addWidget(spinBox)
- # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
- # 數量可設定,增加彈力
- layout.addStretch(1)
- # 加入 slider 並設為 child
- layout.addWidget(slider)
- # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
- # 數量可設定,增加彈力
- layout.addStretch(2)
-
- # 建立 widget 元件,並為 top-level window
- widget = QWidget()
- # 設定 layout 元件,並設為 child
- widget.setLayout(layout)
- # 顯示,因圖形元件被創造時都是 hidden 狀態
- widget.show()
-
- # app.exec_() 讓 QApplication 進入 event loop
- # exec 是 Python keyword,所以會多出底線
- sys.exit(app.exec_())
簡單 OOP 寫法
建議使用 OOP 撰寫 PyQt
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
- from PyQt5.QtGui import QIcon
-
-
- class Example(QWidget):
-
- def __init__(self, parent = None):
- # 繼承的 parent 初始化 fucntion
- super().__init__(parent)
-
- self.initUI()
-
-
- def initUI(self):
- # 設定位置尺寸
- # 同 self.move(300, 300)
- # 同 self.resize(250, 150)
- self.setGeometry(300, 300, 250, 150)
- # 設定標題
- self.setWindowTitle('Simple')
- # 顯示,因圖形元件被創造時都是 hidden 狀態
- self.show()
-
-
- if __name__ == '__main__':
- # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
- app = QApplication(sys.argv)
- # 建立 Exxample instance
- ex = Example()
- # app.exec_() 讓 QApplication 進入 event loop
- # exec 是 Python keyword,所以會多出底線
- sys.exit(app.exec_())
簡單 Main Window 範例
- QMainWindow
- 預設內建 menubar、toolbar 跟 status bar
- QWidget 可擁有這些元件,但必須自行調整
- 擁有自己的 layout 風格如圖,無法變更
- central widget 必須被指定,不然顯示會有問題

- import sys
- from PyQt5.QtCore import Qt
- from PyQt5.QtWidgets import QMainWindow, QWidget, QDockWidget, QHBoxLayout, QPushButton, QTextEdit, QAction, QApplication, QDesktopWidget
- from PyQt5.QtGui import QIcon
-
-
- class Example(QMainWindow):
-
- def __init__(self, parent = None):
- # 繼承的 parent 初始化 fucntion
- super().__init__(parent)
-
- self.initUI()
-
-
- def initUI(self):
- # & + 字元,可設定快捷鍵 Alt + 字元
- # Qt 設定 action focus 的簡便方法
- button1 = QPushButton("H&ello1!")
- button2 = QPushButton("&Hello2!")
-
- # 基本排版元件,有 QHBoxLayout() & QVBoxLayout()
- layout = QHBoxLayout()
- # 加入 button 並設為 child
- layout.addWidget(button1)
- layout.addWidget(button2)
-
- # 建立 QWidget 元件
- widget = QWidget()
- # 設定 layout 元件,並設為 child
- widget.setLayout(layout)
- # 設定主要 widget
- self.setCentralWidget(widget)
-
- # 建立 QTextEdit
- textEdit = QTextEdit()
-
- # 建立 QDockWidget 附屬視窗
- dockwidget = QDockWidget()
- # 設定特性 AllDockWidgetFeatures => DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable
- dockwidget.setFeatures(QDockWidget.DockWidgetClosable)
- # 設定可能的擺放位置
- dockwidget.setAllowedAreas(Qt.LeftDockWidgetArea|Qt.TopDockWidgetArea)
- # 設定 widget 為 textEdit 並設為 child
- dockwidget.setWidget(textEdit)
- # 可由 allowedAreas() 得知可擺放的位置,但不理會也會成功設定
- self.addDockWidget(Qt.RightDockWidgetArea, dockwidget);
-
-
- # 建立 QAction 並設置 Icon,Parent 為 self
- # QAction 可用在 menu 或 toolbar,且可重覆使用
- # exit.jpg 需自行定義
- exitAction = QAction(QIcon('exit.jpg'), 'Exit', self)
- # 設定快捷鍵
- exitAction.setShortcut('Ctrl+Q')
- # 設定 status bar 顯示
- exitAction.setStatusTip('Exit application')
- exitAction.triggered.connect(self.close)
-
- # 回傳 statusbar,若不存在則建立
- statusbar = self.statusBar()
-
- # 回傳 menuBar,若不存在則建立
- menubar = self.menuBar()
- # 建立 menu 清單
- fileMenu = menubar.addMenu('&File')
- # 附加 exitAction
- fileMenu.addAction(exitAction)
-
- # 回傳 toolBar,若不存在則建立
- toolbar = self.addToolBar('Exit')
- # 附加 exitAction
- toolbar.addAction(exitAction)
-
- # 設定尺寸
- self.resize(500, 500)
-
- # 設定標題
- self.setWindowTitle('Simple')
-
- # 顯示,因圖形元件被創造時都是 hidden 狀態
- self.show()
-
-
- # 確定系統已畫,尺寸才會正確
- # 此時 frameGeometry 位置仍是錯的,因尚未把視窗放好
- def showEvent(self, e):
- super().showEvent(e)
-
- # 視窗置中
- self.center()
-
-
- def center(self):
- # 得到 frameGeometry 的 QRect
- qr = self.frameGeometry()
-
- # QDesktopWidget 可得到和桌面相關的資訊
- # 得到桌面可用的 geometry 的中心點
- cp = QDesktopWidget().availableGeometry().center()
-
- # 將 qr 的中心點移至此中心點
- qr.moveCenter(cp)
-
- # 將視窗的左上角移至 qr 的左上角座標
- self.move(qr.topLeft())
-
-
- if __name__ == '__main__':
- # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
- app = QApplication(sys.argv)
- # 建立 Exxample instance
- ex = Example()
- # app.exec_() 讓 QApplication 進入 event loop
- # exec 是 Python keyword,所以會多出底線
- sys.exit(app.exec_())
簡單 OpenCV 範例
- import sys
- import cv2
- from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QScrollArea, QDesktopWidget, QSizePolicy
- from PyQt5.QtGui import QImage, QPixmap, QPalette
-
-
- class Example(QMainWindow):
-
- def __init__(self, parent = None):
- # 繼承的 parent 初始化 fucntion
- super().__init__(parent)
-
- self.initUI()
-
-
- def initUI(self):
- # 建立 QLabel 元件
- imgLabel = QLabel()
-
- # openCV 讀檔
- cvImage = cv2.imread("test.jpg")
- # 得到 大小 與 幾個 byte 組成一個顏色
- height, width, byteValue = cvImage.shape
- # 得到寬有多少 byte
- byteValue = byteValue * width
-
- # openCV 預設顏色排列為 BGR 故需再轉換為 RGB
- temp = cv2.cvtColor(cvImage, cv2.COLOR_BGR2RGB)
- # 設定 imgLabel 圖片
- # 因 setPixmap 輸入需為 QPixmap,所以還得多做一層轉換
- imgLabel.setPixmap(QPixmap().fromImage(QImage(temp, width, height, byteValue, QImage.Format_RGB888)))
-
- # 建立 QScrollArea for 滾動圖片
- scrollArea = QScrollArea()
- # 設定背景顏色
- scrollArea.setBackgroundRole(QPalette.Dark)
- # 將 imgLabel 設定為 child
- scrollArea.setWidget(imgLabel)
-
- # 設定主要 widget
- self.setCentralWidget(scrollArea)
- # 設定尺寸
- self.resize(500, 500)
- # 視窗置中
- self.center()
- # 設定標題
- self.setWindowTitle('Simple')
- # 顯示,因圖形元件被創造時都是 hidden 狀態
- self.show()
-
- def center(self):
- # 得到 frameGeometry 的 QRect
- qr = self.frameGeometry()
-
- # QDesktopWidget 可得到和桌面相關的資訊
- # 得到桌面可用的 geometry 的中心點
- cp = QDesktopWidget().availableGeometry().center()
-
- # 將 qr 的中心點移至此中心點
- qr.moveCenter(cp)
-
- # 將視窗的左上角移至 qr 的左上角座標
- self.move(qr.topLeft())
-
-
- if __name__ == '__main__':
- # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
- app = QApplication(sys.argv)
- # 建立 Exxample instance
- ex = Example()
- # app.exec_() 讓 QApplication 進入 event loop
- # exec 是 Python keyword,所以會多出底線
- sys.exit(app.exec_())
簡單設計方法
使用官方的 designer.exe 設計 GUI 並存檔為 .ui
轉換方法
python -m PyQt5.uic.pyuic xxx.ui > xxx.py
PS. 直接用 pip 安裝並不會有此 designer.exe,需至官網下載安裝後才有
Componets 介紹
- 範例可使用 python qtdemo.pyw 觀看
- 位置:...\site-packages\PyQt5\examples\qtdemo
- QAxContainer
- 控制 ActiveX controls 跟 COM objects
- 不支援寫入 ActiveX servers in Python
- 只限於 Windows
- QtBluetooth
- QtCore
- 主要的核心 classes,像是 event loop 和 Qt’s signal and slot mechanism.
- 另外還有 abstractions for animations,state machines,threads,mapped files, shared memory,regular expressions 和 user and application settings
- QtDBus
- D-Bus protocol
- 不支援 Windows.
- QtDesigner
- QtGui
- windowing system integration,event handling,2D graphics,basic imaging,fonts 和 text.
- OpenGL 和 OpenGL ES bindings
- QtHelp
- QtLocation
- 控制 geocoding,navigation information,位置尋找
- QtMacExtras
- 額外的 classes for OS X 和 iOS
- QtMultimedia
- multimedia content and APIs to access camera and radio functionality
- QtMultimediaWidgets
- 元件可 handle multimedia content
- QtNetwork
- UDP and TCP clients and servers
- HTTP clients and support DNS lookups
- QtNfc
- QtOpenGL
- QtPositioning
- 定位借由 satellite,Wi-Fi,a text file,and so on
- QtPrintSupport
- 影印功能,甚至可產生 PostScript 和 PDF
- QtQml
- QtQuick
- 基本元件 for creating user interfaces with QML.
- QtQuickWidgets
- 顯示 QML scene in a traditional widget.
- QtSensors
- Sensor 控制,像是 accelerometers,altimeters,ambient light,temperature sensors,gyroscopes 和 magnetometers
- 未支援 gestures
- QtSerialPort
- QtSql
- QtSvg
- QtTest
- 測試
- PyQt5 不支援,因 python 本身有更好用的 unittest
- QtWebChannel
- 控制 QObject or QML objects from HTML clients.
- QtWebEngine
- Web Engine objects created in QML to Python.
- QtWebEngineCore
- QtWebEngineWidgets 的核心 classes
- QtWebEngineWidgets
- Chromium based implementation of a web browser
- 取代 QtWebKit 擁有更好的功能,但消耗更多資源,且無法直接利用 Python APIs 控制 network 跟 HTML
- Windows 只支援 v3.5+
- QtWebKit
- WebKit2 based implementation of a web browser
- QtWebKitWidgets
- WebKit1 based implementation of a web browser
- QtWebSockets
- WebSocket protocol described in RFC 6455
- QtWidgets
- QtWinExtras
- QtX11
- QtXml
- SAX and DOM interfaces to Qt’s XML parser.
- QtXmlPatterns
- XPath, XQuery, XSLT and XML Schema validation.
- Enginio
- Qt Cloud Services Managed Application Runtime.
- Qt
- uic
- 控制 .ui files created by Qt Designer
- 轉換指令:python -m PyQt5.uic.pyuic xxx.ui > xxx.py
參考
PyQt5 tutorial
PyQt 实践教学(一)--First programs in PyQt5
[PyQt 教學] Part 1: Introduction
留言
張貼留言