[Python] PyQt5

程式語言:Python
Package:PyQt5
官網
官網文件

功能:建立 GUI 人機介面

範例

簡單視窗
  1. import sys
  2. from PyQt5.QtWidgets import QApplication, QWidget
  3.  
  4.  
  5. if __name__ == '__main__':
  6. # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
  7. app = QApplication(sys.argv)
  8.  
  9. # 建立 QWidget
  10. w = QWidget()
  11. # 設定尺寸
  12. w.resize(250, 150)
  13. # 設定位置
  14. w.move(300, 300)
  15. # 設定標題
  16. w.setWindowTitle('Simple')
  17. # 顯示,因圖形元件被創造時都是 hidden 狀態
  18. w.show()
  19.  
  20. # app.exec_() 讓 QApplication 進入 event loop
  21. # exec 是 Python keyword,所以會多出底線
  22. sys.exit(app.exec_())
簡單按鈕
  1. import sys
  2. from PyQt5.QtWidgets import QApplication, QPushButton
  3.  
  4.  
  5. if __name__ == '__main__':
  6. # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
  7. app = QApplication(sys.argv)
  8.  
  9. # & + 字元,可設定快捷鍵 Alt + E
  10. # Qt 設定 action focus 的簡便方法
  11. button = QPushButton("H&ello!")
  12. # 設定尺寸
  13. button.resize(200, 75)
  14. # 設定位置
  15. button.move(500, 400)
  16. # 設定視窗標題
  17. button.setWindowTitle("Hello World")
  18. # 顯示,因圖形元件被創造時都是 hidden 狀態
  19. button.show()
  20.  
  21. # app.exec_() 讓 QApplication 進入 event loop
  22. # exec 是 Python keyword,所以會多出底線
  23. 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
  1. import sys
  2. from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
  3.  
  4.  
  5. if __name__ == '__main__':
  6. # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
  7. app = QApplication(sys.argv)
  8.  
  9. # & + 字元,可設定快捷鍵 Alt + E
  10. # Qt 設定 action focus 的簡便方法
  11. ok = QPushButton("&OK")
  12. cancel = QPushButton("&Cancel")
  13.  
  14. # 基本排版元件,有 QHBoxLayout() & QVBoxLayout()
  15. layout = QHBoxLayout()
  16. # 加入 ok button 並設為 child
  17. layout.addWidget(ok)
  18. # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
  19. # 數量可設定,增加彈力
  20. layout.addStretch(1)
  21. # 加入 cancel button 並設為 child
  22. layout.addWidget(cancel)
  23. # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
  24. # 數量可設定,增加彈力
  25. layout.addStretch(2)
  26. # 建立 widget 元件,並為 top-level window
  27. widget = QWidget()
  28. # 設定 layout 元件,並設為 child
  29. widget.setLayout(layout)
  30. # 顯示,因圖形元件被創造時都是 hidden 狀態
  31. widget.show()
  32.  
  33. # app.exec_() 讓 QApplication 進入 event loop
  34. # exec 是 Python keyword,所以會多出底線
  35. sys.exit(app.exec_())
簡單 Signals & Slots 範例
  • 多 singals 對 多 slots
  • slots 可為任意 function
  • 參數可為 Python 任意型態
  • signal 與 signal 可互相連接,產生連鎖反應
  • 可 connect,也可 disconnect
  1. import sys
  2. from PyQt5.QtCore import Qt
  3. from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QSpinBox, QSlider, QMessageBox
  4.  
  5. def helloWorld():
  6. QMessageBox.information(None, 'Message', 'Hello World', QMessageBox.Ok)
  7.  
  8. if __name__ == '__main__':
  9. # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
  10. app = QApplication(sys.argv)
  11. # & + 字元,可設定快捷鍵 Alt + E
  12. # Qt 設定 action focus 的簡便方法
  13. button = QPushButton("H&ello!")
  14. # 建立 QSpinBox
  15. spinBox = QSpinBox()
  16. # 設定前罝符號
  17. spinBox.setPrefix("$")
  18. # 設定範圍
  19. spinBox.setRange(0, 100)
  20. # 建立橫向 QSlider
  21. slider = QSlider(Qt.Horizontal)
  22. # 設定範圍
  23. slider.setRange(0, 100)
  24. # signals 連接 slots
  25. button.clicked.connect(helloWorld)
  26. spinBox.valueChanged.connect(slider.setValue)
  27. slider.valueChanged.connect(spinBox.setValue)
  28.  
  29. # 基本排版元件,有 QHBoxLayout() & QVBoxLayout()
  30. layout = QHBoxLayout()
  31. # 加入 ok button 並設為 child
  32. layout.addWidget(button)
  33. # 加入 spinBox 並設為 child
  34. layout.addWidget(spinBox)
  35. # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
  36. # 數量可設定,增加彈力
  37. layout.addStretch(1)
  38. # 加入 slider 並設為 child
  39. layout.addWidget(slider)
  40. # 加入彈簧元件,可將兩邊元件推到底,用在視窗放大時的介面調整
  41. # 數量可設定,增加彈力
  42. layout.addStretch(2)
  43. # 建立 widget 元件,並為 top-level window
  44. widget = QWidget()
  45. # 設定 layout 元件,並設為 child
  46. widget.setLayout(layout)
  47. # 顯示,因圖形元件被創造時都是 hidden 狀態
  48. widget.show()
  49.  
  50. # app.exec_() 讓 QApplication 進入 event loop
  51. # exec 是 Python keyword,所以會多出底線
  52. sys.exit(app.exec_())
簡單 OOP 寫法
建議使用 OOP 撰寫 PyQt
  1. import sys
  2. from PyQt5.QtWidgets import QApplication, QWidget
  3. from PyQt5.QtGui import QIcon
  4.  
  5.  
  6. class Example(QWidget):
  7. def __init__(self, parent = None):
  8. # 繼承的 parent 初始化 fucntion
  9. super().__init__(parent)
  10. self.initUI()
  11. def initUI(self):
  12. # 設定位置尺寸
  13. # 同 self.move(300, 300)
  14. # 同 self.resize(250, 150)
  15. self.setGeometry(300, 300, 250, 150)
  16. # 設定標題
  17. self.setWindowTitle('Simple')
  18. # 顯示,因圖形元件被創造時都是 hidden 狀態
  19. self.show()
  20. if __name__ == '__main__':
  21. # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
  22. app = QApplication(sys.argv)
  23. # 建立 Exxample instance
  24. ex = Example()
  25. # app.exec_() 讓 QApplication 進入 event loop
  26. # exec 是 Python keyword,所以會多出底線
  27. sys.exit(app.exec_())
簡單 Main Window 範例
  • QMainWindow
    • 預設內建 menubar、toolbar 跟 status bar
    • QWidget 可擁有這些元件,但必須自行調整
    • 擁有自己的 layout 風格如圖,無法變更
    • central widget 必須被指定,不然顯示會有問題
  1. import sys
  2. from PyQt5.QtCore import Qt
  3. from PyQt5.QtWidgets import QMainWindow, QWidget, QDockWidget, QHBoxLayout, QPushButton, QTextEdit, QAction, QApplication, QDesktopWidget
  4. from PyQt5.QtGui import QIcon
  5.  
  6.  
  7. class Example(QMainWindow):
  8. def __init__(self, parent = None):
  9. # 繼承的 parent 初始化 fucntion
  10. super().__init__(parent)
  11. self.initUI()
  12. def initUI(self):
  13. # & + 字元,可設定快捷鍵 Alt + 字元
  14. # Qt 設定 action focus 的簡便方法
  15. button1 = QPushButton("H&ello1!")
  16. button2 = QPushButton("&Hello2!")
  17. # 基本排版元件,有 QHBoxLayout() & QVBoxLayout()
  18. layout = QHBoxLayout()
  19. # 加入 button 並設為 child
  20. layout.addWidget(button1)
  21. layout.addWidget(button2)
  22. # 建立 QWidget 元件
  23. widget = QWidget()
  24. # 設定 layout 元件,並設為 child
  25. widget.setLayout(layout)
  26. # 設定主要 widget
  27. self.setCentralWidget(widget)
  28. # 建立 QTextEdit
  29. textEdit = QTextEdit()
  30. # 建立 QDockWidget 附屬視窗
  31. dockwidget = QDockWidget()
  32. # 設定特性 AllDockWidgetFeatures => DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable
  33. dockwidget.setFeatures(QDockWidget.DockWidgetClosable)
  34. # 設定可能的擺放位置
  35. dockwidget.setAllowedAreas(Qt.LeftDockWidgetArea|Qt.TopDockWidgetArea)
  36. # 設定 widget 為 textEdit 並設為 child
  37. dockwidget.setWidget(textEdit)
  38. # 可由 allowedAreas() 得知可擺放的位置,但不理會也會成功設定
  39. self.addDockWidget(Qt.RightDockWidgetArea, dockwidget);
  40. # 建立 QAction 並設置 Icon,Parent 為 self
  41. # QAction 可用在 menu 或 toolbar,且可重覆使用
  42. # exit.jpg 需自行定義
  43. exitAction = QAction(QIcon('exit.jpg'), 'Exit', self)
  44. # 設定快捷鍵
  45. exitAction.setShortcut('Ctrl+Q')
  46. # 設定 status bar 顯示
  47. exitAction.setStatusTip('Exit application')
  48. exitAction.triggered.connect(self.close)
  49. # 回傳 statusbar,若不存在則建立
  50. statusbar = self.statusBar()
  51.  
  52. # 回傳 menuBar,若不存在則建立
  53. menubar = self.menuBar()
  54. # 建立 menu 清單
  55. fileMenu = menubar.addMenu('&File')
  56. # 附加 exitAction
  57. fileMenu.addAction(exitAction)
  58. # 回傳 toolBar,若不存在則建立
  59. toolbar = self.addToolBar('Exit')
  60. # 附加 exitAction
  61. toolbar.addAction(exitAction)
  62. # 設定尺寸
  63. self.resize(500, 500)
  64. # 設定標題
  65. self.setWindowTitle('Simple')
  66.  
  67. # 顯示,因圖形元件被創造時都是 hidden 狀態
  68. self.show()
  69. # 確定系統已畫,尺寸才會正確
  70. # 此時 frameGeometry 位置仍是錯的,因尚未把視窗放好
  71. def showEvent(self, e):
  72. super().showEvent(e)
  73. # 視窗置中
  74. self.center()
  75.  
  76.  
  77. def center(self):
  78. # 得到 frameGeometry 的 QRect
  79. qr = self.frameGeometry()
  80. # QDesktopWidget 可得到和桌面相關的資訊
  81. # 得到桌面可用的 geometry 的中心點
  82. cp = QDesktopWidget().availableGeometry().center()
  83. # 將 qr 的中心點移至此中心點
  84. qr.moveCenter(cp)
  85. # 將視窗的左上角移至 qr 的左上角座標
  86. self.move(qr.topLeft())
  87. if __name__ == '__main__':
  88. # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
  89. app = QApplication(sys.argv)
  90. # 建立 Exxample instance
  91. ex = Example()
  92. # app.exec_() 讓 QApplication 進入 event loop
  93. # exec 是 Python keyword,所以會多出底線
  94. sys.exit(app.exec_())
簡單 OpenCV 範例
  1. import sys
  2. import cv2
  3. from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QScrollArea, QDesktopWidget, QSizePolicy
  4. from PyQt5.QtGui import QImage, QPixmap, QPalette
  5.  
  6.  
  7. class Example(QMainWindow):
  8. def __init__(self, parent = None):
  9. # 繼承的 parent 初始化 fucntion
  10. super().__init__(parent)
  11. self.initUI()
  12. def initUI(self):
  13. # 建立 QLabel 元件
  14. imgLabel = QLabel()
  15. # openCV 讀檔
  16. cvImage = cv2.imread("test.jpg")
  17. # 得到 大小 與 幾個 byte 組成一個顏色
  18. height, width, byteValue = cvImage.shape
  19. # 得到寬有多少 byte
  20. byteValue = byteValue * width
  21. # openCV 預設顏色排列為 BGR 故需再轉換為 RGB
  22. temp = cv2.cvtColor(cvImage, cv2.COLOR_BGR2RGB)
  23. # 設定 imgLabel 圖片
  24. # 因 setPixmap 輸入需為 QPixmap,所以還得多做一層轉換
  25. imgLabel.setPixmap(QPixmap().fromImage(QImage(temp, width, height, byteValue, QImage.Format_RGB888)))
  26. # 建立 QScrollArea for 滾動圖片
  27. scrollArea = QScrollArea()
  28. # 設定背景顏色
  29. scrollArea.setBackgroundRole(QPalette.Dark)
  30. # 將 imgLabel 設定為 child
  31. scrollArea.setWidget(imgLabel)
  32. # 設定主要 widget
  33. self.setCentralWidget(scrollArea)
  34. # 設定尺寸
  35. self.resize(500, 500)
  36. # 視窗置中
  37. self.center()
  38. # 設定標題
  39. self.setWindowTitle('Simple')
  40. # 顯示,因圖形元件被創造時都是 hidden 狀態
  41. self.show()
  42. def center(self):
  43. # 得到 frameGeometry 的 QRect
  44. qr = self.frameGeometry()
  45. # QDesktopWidget 可得到和桌面相關的資訊
  46. # 得到桌面可用的 geometry 的中心點
  47. cp = QDesktopWidget().availableGeometry().center()
  48. # 將 qr 的中心點移至此中心點
  49. qr.moveCenter(cp)
  50. # 將視窗的左上角移至 qr 的左上角座標
  51. self.move(qr.topLeft())
  52. if __name__ == '__main__':
  53. # Qt GUI 需要唯一一個 QApplication 負責管理,可傳入 sys.argv 參數
  54. app = QApplication(sys.argv)
  55. # 建立 Exxample instance
  56. ex = Example()
  57. # app.exec_() 讓 QApplication 進入 event loop
  58. # exec 是 Python keyword,所以會多出底線
  59. 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
    • Bluetooth
  • 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
    • 自定義 Qt Designer 元件
  • QtGui
    • windowing system integration,event handling,2D graphics,basic imaging,fonts 和 text. 
    • OpenGL 和 OpenGL ES bindings
  • QtHelp
    • 建立 Help 文件
  • 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
    • NFC 控制
  • QtOpenGL
    • OpenGL
  • QtPositioning
    • 定位借由 satellite,Wi-Fi,a text file,and so on
  • QtPrintSupport
    • 影印功能,甚至可產生 PostScript 和 PDF
  • QtQml
    • QML 和 JavaScript
  • 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
    • serial ports
  • QtSql
    • SQL 控制
  • QtSvg
    • SVG 控制
  • 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
    • UI elements
  • QtWinExtras
    • 額外的 classes for Window
  • QtX11
    • X11
  • 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
    • 包含以上所有 package
  • 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

留言