安裝引導
學前參考
這一篇文章教學整理的不錯,重點都有記錄在裡面,但是也有些重點沒有記載,需要自己在摸索挖掘唷!
本篇我會記載著,我個人常用的QT5
代碼,並且會持續更新。
⬇⬇⬇文章開始⬇⬇⬇
開始介紹
我開始接觸 QT5 的原因是因為我正在自學 Python 並為一家公司設計一個缺陷視覺識別系統。為了讓這家公司方便操作 GUI 界面,我開始學習如何使用 QT5 來設計 Python 程序的 GUI 界面。
轉換 .ui 檔案為 .py 程式碼檔案
回到輸入指令的畫面,輸入下列指令,就能將 .ui 檔案轉換為 .py 的程式碼檔案。
1
| pyuic5 -o qt_test.py -x qt_test.ui
|
QtCore.pyqtSignal 信號
由於QT5
都是「無窮迴圈」運作的原因,若直接將QT5
的元件指令,放到QThread多執行緒
裡執行,會導致Python程序運作卡住,並停止運作。所以我們要先學會利用信號來執行你要執行的元件指令
,這個信號有點像是按鈕開關,但是它也可以傳int,數字透過判斷式,選擇執行的代碼。
QtCore.pyqtSignal 僅支援 class 寫法。
在 PyQt5 裡的元件,都是透過信號的傳遞進行溝通和互動,雖然大部分的元件都有 connect 接收訊息的機制,但也可以使用 QtCore.pyqtSignal 的方式自訂信號進行傳遞。
class的寫法代碼演示(點擊展開)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import QObject, pyqtSignal
class Ui_MainWindow(QObject): label_show_ON = pyqtSignal(int) def label_show(self,show): if show == 1: self.label.setText("A") if show == 2: self.label.setText("B")
def A(self): self.label_show_ON.emit(1)
def B(self): self.label_show_ON.emit(2) def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(221, 100) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButtonA = QtWidgets.QPushButton(self.centralwidget) self.pushButtonA.setGeometry(QtCore.QRect(20, 20, 75, 23)) self.pushButtonA.setObjectName("pushButtonA") self.pushButtonB = QtWidgets.QPushButton(self.centralwidget) self.pushButtonB.setGeometry(QtCore.QRect(130, 20, 75, 23)) self.pushButtonB.setObjectName("pushButtonB") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(20, 50, 181, 21)) self.label.setAlignment(QtCore.Qt.AlignCenter) self.label.setObjectName("label") MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow): translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(translate("MainWindow", "TEST")) self.pushButtonA.setText(translate("MainWindow", "Button A")) self.pushButtonB.setText(translate("MainWindow", "Button B")) self.label.setText(translate("MainWindow", "TextLabel")) self.label_show_ON.connect(self.label_show) self.pushButtonA.clicked.connect(self.A) self.pushButtonB.clicked.connect(self.B)
if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
|
QThread 多執行緒
使用 PyQt5 設計介面時,視窗主程式的本質是放在一個「無窮迴圈」裡執行,如果需要加入多個迴圈且不影響主視窗 ( 如果單純放入迴圈,會在所有迴圈結束後才啟動視窗 ),就需要使用 QThread 機制,讓多個執行緒同時執行,這裡會介紹 QThread 的使用方式,還會額外介紹搭配 Python threading 標準函式庫的作法。
一般的寫法(點擊展開)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| from PyQt5 import QtWidgets from PyQt5.QtCore import QThread import sys, time
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget() Form.setWindowTitle('oxxo.studio') Form.resize(300, 200)
label_a = QtWidgets.QLabel(Form) label_a.setGeometry(10, 10, 100, 30)
label_b = QtWidgets.QLabel(Form) label_b.setGeometry(10, 50, 100, 30)
def a(): for i in range(0,5): label_a.setText(str(i)) print('A:',i) time.sleep(0.5)
def b(): for i in range(0,50,10): label_b.setText(str(i)) print('B:',i) time.sleep(0.5)
thread_a = QThread() thread_a.run = a thread_a.start()
thread_b = QThread() thread_b.run = b thread_b.start()
Form.show() sys.exit(app.exec_())
|
class的寫法(點擊展開)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import QThread import time
class Ui_MainWindow(object): def a(self): for i in range(0,5): self.label_1.setText(str(i)) print('A:',i) time.sleep(1)
def b(self): for i in range(0,50,10): self.label_2.setText(str(i)) print('B:',i) time.sleep(1)
def run(self): self.thread_a.start() self.thread_b.start()
def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(221, 100) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(20, 20, 75, 23)) self.pushButton.setObjectName("pushButton") self.label_1 = QtWidgets.QLabel(self.centralwidget) self.label_1.setGeometry(QtCore.QRect(20, 50, 71, 21)) self.label_1.setAlignment(QtCore.Qt.AlignCenter) self.label_1.setObjectName("label_1") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(130, 50, 71, 21)) self.label_2.setAlignment(QtCore.Qt.AlignCenter) self.label_2.setObjectName("label_2") MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "TEST")) self.pushButton.setText(_translate("MainWindow", "Button A")) self.thread_a = QThread() self.thread_a.run = self.a self.thread_b = QThread() self.thread_b.run = self.b self.pushButton.clicked.connect(self.run)
if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
|
QThread 常用方法
方法 |
參數 |
說明 |
start() |
無 |
啟動執行緒 |
wait() |
無 |
等待該執行緒結束 |
sleep() |
Sec |
等待該執行緒幾秒 |
保存關閉QT介面的當前值
目的是關閉QT時保存上次的執行結果,並且再下一次開啟程式時,可以繼續引用上次執行的結果值。
1 2 3 4 5 6 7
| def setupUi(self, WindowForms): self.settings = QSettings('MyCompany', 'yolov5-AINTEC') self.settings_save = QThread()
self.settings_save.run = self.settings_save_data self.settings_save.start()
|
保存變數值到索引
1 2 3 4 5 6 7
| def settings_save_data(self): try: while True: self.settings.setValue('Setting_bool1', self.SettingOther_radioButton_1.isChecked()) except: pass
|
調用保存索引的變數值
1 2 3
| a = self.settings.value('CCDtest1', defaultValue=0, type=int) b = self.settings.value('Setting_bool1', defaultValue=False, type=bool) c = self.settings.value('threshold_mode_1', defaultValue='無')
|