python3 pyqt5 opencv3簡單使用(慢慢更新中)

python3 pyqt5 opencv3簡單使用(慢慢更新中)

關於python3下搭建pyqt5(pycharm)參考這條連結

對於pyqt的使用個人比較建議ui設計邏輯功能分開開發。

下面介紹下簡單的使用(通過左側的目錄可直接跳轉到相應模組):

ui介面的建立

通過pycharm的Tools->External Tools->QtDesigner開啟介面設計視窗(本文以建立一個Main Window為例)。
通過拖拽可以簡單的設計介面,設計好後儲存UI檔案(本文建立的檔名為GUI),對UI檔案點選滑鼠反鍵選擇External Tools->PyUIC,會生成一個對應UI介面的GUI.py檔案。
接下來為了讓UI設計檔案與邏輯功能檔案分開,在新建一個py檔案,匯入剛生成的GUI.py中的 Ui_MainWindow。
import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
from GUI import Ui_MainWindow  # 匯入建立的GUI類
class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):  
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = mywindow()
window.show()
sys.exit(app.exec_())

OK!一個超級簡單的UI設計以及UI的呼叫全部完成。

接下來再寫點基礎UI開發中常用到的功能:

PyQt視窗介面位置以及透明度調節

下面介紹幾個函式用來調節視窗介面的位置以及介面邊框和背景的隱藏。

在邏輯功能檔案的初始化中進行設定:

import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
from main_window import Ui_MainWindow  # 匯入建立的GUI類
class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
# setting main window geometry
desktop_geometry = QtWidgets.QApplication.desktop()  # 獲取螢幕大小
main_window_width = desktop_geometry.width()  # 螢幕的寬
main_window_height = desktop_geometry.height()  # 螢幕的高
rect = self.geometry()  # 獲取視窗介面大小
window_width = rect.width()  # 視窗介面的寬
window_height = rect.height()  # 視窗介面的高
x = (main_window_width - window_width) // 2  # 計算視窗左上角點橫座標
y = (main_window_height - window_height) // 2  # 計算視窗左上角點縱座標
self.setGeometry(x, y, window_width, window_height)  # 設定視窗介面在螢幕上的位置
# 無邊框以及背景透明一般不會在主視窗中用到,一般使用在子視窗中,例如在子視窗中顯示gif提示載入資訊等等
        self.setWindowFlags(Qt.FramelessWindowHint)  # 無邊框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 背景透明

Pyqt中的常用小控制元件

QPushbutton的簡單使用

首先開啟QtDesigner通過滑鼠新增一個pushbutton,雙擊進行更改pushbutton的text。
接下來對pushbutton反鍵選擇Change objectName進行修改,這個名稱是在邏輯功能設計時呼叫的名稱。重要!


修改完之後進行儲存,記得每次修改後都要對UI檔案反鍵進行External Tools->PyUIC操作對GUI.py檔案進行更新。
接著進入邏輯功能檔案,新增pushbutton對應的響應函式與槽連線。
設計pushbutton點選對應的響應函式:
class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
def pushbutton_fuction(self):   # pushbutton對應的響應函式
# do some things

新增槽連線:

class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
self.one_pushButton.clicked.connect(pushbutton_fuction)   # one_pushButton是對應的objectName
# 將點選事件與槽函式進行連線
def pushbutton_fuction(self):
# do some things

QLabel與opencv讀取並顯示圖片

首先新增一個QLabel,修改text內容以及Change objectName.

接下來我們要實現通過點選一個pushbutton在QLabel中顯示一張圖片。

class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
self.one_pushButton.clicked.connect(pushbutton_fuction)
def pushbutton_fuction(self):
Im = cv2.imread('***.jpg')  # 通過Opencv讀入一張圖片
image_height, image_width, image_depth = Im.shape  # 獲取影象的高,寬以及深度。
QIm = cv2.cvtColor(Im, cv2.COLOR_BGR2RGB)  # opencv讀圖片是BGR,qt顯示要RGB,所以需要轉換一下
QIm = QImage(QIm.data, image_width, image_height,  # 建立QImage格式的影象,並讀入影象資訊
image_width * image_depth,
QImage.Format_RGB888)
self.image_label.setPixmap(QPixmap.fromImage(QIm))  # 將QImage顯示在之前建立的QLabel控制元件中
如果想讓圖片適應QLabel的大小,在 __init__中新增一行程式碼:
self.image_label.setScaledContents(True)
如果想自定義QLabel的大小以及位置,可以用:
self.image_label.setGeometry(x, y, width, height)

QLineEdit的讀取與寫入

QLineEdit控制元件常用的就是讀取與寫入兩個功能:
self.my_lineEdit.text()  # 讀取QLineEdit中的內容
self.my_lineEdit.setText('show some text')  # 將字串寫入QLineEdit中
self.my_lineEdit.clear()  # 清除QLineEdit中的資訊

QCheckBox的使用

QCheckBox主要是檢查其勾選狀態,或者連線改變狀態觸發事件,常用函式如下:
self.my_checkbox.stateChanged.connect(self.related_function)  # 將checkbox狀態變化事件連線相應函式
self.my_checkbox.isChecked()  # 檢查checkbox是否被勾選
self.my_checkbox.setCheckState(QtCore.Qt.Unchecked)  # 將checkbox狀態設定為未勾選狀態
# QtCore.Qt.Checked 為勾選狀態

QCombo box的使用

首先通過QtDesigner將Comb box控制元件託至介面中,雙擊Combo box控制元件在彈出的介面中點選左下角的加號新增選項:

獲取Combo box選擇資訊的常用方法主要有兩種,一種是獲取選項的index一種是直接獲取選項的文字。

self.image_type_comboBox.currentIndex()   # 獲取當前選項的Index(int)
self.image_type_comboBox.currentText()    # 獲取當前選項的文字(Qstring)

QMovie的使用

QMovie可將gif動態圖在label中進行顯示。用起來也非常簡單。

Movie = QMovie('time.gif')  # 載入Gif圖,注意QMovie在PyQt5.QtCore內
self.movie_label.setMovie(Movie)  # 將gif顯示在gif中
Movie.start()  # 啟動gif
Movie.stop()   # 停止gif

pyqt中的常用小功能

通過QFileDialog選擇檔案或者資料夾

directory = QFileDialog.getExistingDirectory(self,  
"選取資料夾",  
"D:/")   # 開啟路徑為D盤,若不指定路徑,預設開啟當前py檔案所在資料夾
fileName, filetype = QFileDialog.getOpenFileName(self,  
"選取檔案",  
"C:/",  
"Image Files (*.jpg);;Text Files (*.txt)")   # 設定副檔名過濾,
# 注意用雙分號間隔

QMessageBox簡單用法

information框:
QMessageBox.information(self, 'Information', '提示訊息')

question框:

reply = QMessageBox.question(self,                          
"question",  
"選擇是或否",  
QMessageBox.Yes | QMessageBox.No)

DateTime獲取當前時間命名檔案

通常儲存圖片或者檔案時,會經常糾結如何命名檔案,別想了直接用時間命名吧!

time = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')   # import datetime
save_file_name = time   '.jpg'
cv2.imwrite(save_file_name, save_image)

PyQt選單欄的建立

首先開啟Qt Designer,在介面的最上端雙擊“Type Here”輸入“File(&F)”後按回車鍵,建立一級選單,如圖所示,(&F)表示通過“Alt F”快捷鍵直接開啟。同理建立二級選單等。

建立好選單後在右側menuFile_F一級選單下可以看到相應menu名稱,例如圖中建立的Open file二級選單對應的名稱為actionOpen_file_O

接下來在邏輯功能檔案中的__init__函式下進行槽連線即可。

self.actionOpen_file_O.triggered.connect(self.open_file_function)

PyQt底部狀態列

狀態列的使用主要是顯示一些資訊,便於使用。主要使用兩個函式:
self.statusBar().showMessage()  # 顯示字串
self.statusBar().clearMessage()  # 清除字串

PyQt建立子介面

首先新建一個UI檔案(Widget)sub_window.py以及相應的邏輯功能檔案sub_main.py。

建立相應的邏輯檔案sub_main.py(要將建立的子UI介面匯入):

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
from sub_window import Ui_Form   # 匯入子UI介面
class secondwindow(QtWidgets.QWidget, Ui_Form):   #  建立子UI類
def __init__(self):
super(secondwindow, self).__init__()
self.setupUi(self)

接著在主邏輯檔案中匯入子類,並進行例項化:

import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
from GUI import Ui_MainWindow
from sub_main import secondwindow    # 匯入子UI類
class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
self.second_window = secondwindow()     # 例項化子介面
self.one_pushButton.clicked.connect(pushbutton_fuction)  # 槽函式連線
def pushbutton_fuction(self):
self.second_window.show()   # 通過點選按鈕彈出子介面
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = mywindow()
window.show()
sys.exit(app.exec_())

注意:本示例建立的子視窗繼承自QWidget,是非模態化的視窗(可以同時在子視窗和主視窗上進行操作)。若要建立一個模態化的視窗(只有在關閉子視窗後才能對主視窗進行操作),需要繼承自QDialog,例項化並開啟視窗程式碼如下:

self.second_window = secondwindow()  # 例項化子介面,注意secondwindow繼承自QDialog
self.second_window.exec_()  # 開啟子視窗,注意和非模態化不同

建立pyqt訊號並進行連線

在主邏輯檔案中建立pyqt訊號傳遞到子視窗中:

import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
from GUI import Ui_MainWindow
from sub_main import secondwindow
class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):
emit_image_signal = pyqtSignal(QImage)    # 建立pyqt訊號,指定傳遞的變數型別為QImage
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
self.second_window = secondwindow()     # 例項化子介面
self.one_pushButton.clicked.connect(pushbutton_fuction)
self.emit_image_signal.connect(self.second_window.show_label)    # 將pyqt訊號連線到
# 子視窗的show_label()函式
def pushbutton_fuction(self):
Im = cv2.imread('***.jpg')  # 通過Opencv讀入一張圖片
image_height, image_width, image_depth = Im.shape    # 獲取影象的高,寬以及深度。
QIm = cv2.cvtColor(Im, cv2.COLOR_BGR2RGB)    # opencv讀圖片是BGR,qt顯示要RGB,所以需要轉換一下
QIm = QImage(QIm.data, image_width, image_height,    # 建立QImage格式的影象,並讀入影象資訊
image_width * image_depth,
QImage.Format_RGB888)
self.second_window.show()    #  彈出子視窗
self.emit_image_signal.emit(QIm)   # 釋放pyqt訊號
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = mywindow()
window.show()
sys.exit(app.exec_())

在子邏輯檔案中接收pyqt訊號並繪製影象:

class secondwindow(QtWidgets.QWidget, Ui_Form):   #  建立子UI類
def __init__(self):
super(secondwindow, self).__init__()
self.setupUi(self)
def show_label(self, QIm)
self.image_label.setPixmap(QPixmap.fromImage(QIm))   # 將傳遞進來的圖片顯示在建立好的QLabel控制元件中

pyqt滑鼠事件

使用滑鼠事件首先要開啟滑鼠跟蹤,接著重寫滑鼠事件
class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
self.setMouseTracking(True)     # 開啟滑鼠跟蹤
self.centralwidget.setMouseTracking(True) 
self.image_label.setMouseTracking(True)   # 在image_label中開啟滑鼠跟蹤
def mouseMoveEvent(self, a0: QtGui.QMouseEvent):  # 滑鼠移動事件
#  a0.x()  -> x座標 ; a0.y() -> y座標   
def mousePressEvent(self, a0: QtGui.QMouseEvent):  # 滑鼠點選事件
if a0.button() == Qt.LeftButton:   # 按下滑鼠左鍵
# do something
if a0.button() == Qt.RightButton:  # 按下滑鼠右鍵
# do something
if a0.button() == Qt.MidButton:  # 按下滑鼠中間
# do something
def mouseReleaseEvent(self, a0: QtGui.QMouseEvent):  # 滑鼠釋放事件
# do something

pyqt多執行緒的簡單使用

pyqt多執行緒的使用,主要是先建立一個執行緒類,接著在主執行緒中進行例項化並開啟執行緒
首先建立一個執行緒類,新建一個py檔案:
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
class mythread(QThread):
def __init__(self, parent=None):
super(mythread, self).__init__()
def __del__(self):
self.wait()
def run(self):
#  do something

接著在主函式中匯入自定義執行緒類,例項化並開啟:

import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
from GUI import Ui_MainWindow
from costom_thread import mythread   # 匯入自定義執行緒類
class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
self.one_pushButton.clicked.connect(pushbutton_fuction)  # 槽函式連線
self.sub_thread = mythread()   # 例項化新執行緒
def pushbutton_fuction(self):
self.sub_thread.start()    # 開啟新執行緒
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = mywindow()
window.show()
sys.exit(app.exec_())