PyQt5多個GUI界面設計

版權聲明:本文爲博主原創文章,轉載 請註明出處:https://blog.csdn.net/sc2079/article/details/90454379python

- 寫在前面



  本科畢業設計終於告一段落了。特寫博客記錄作畢業設計(路面裂紋識別)期間的踩過的坑和收穫。但願對你有用。

  目前有:

    1.Tensorflow&CNN:裂紋分類

    2.Tensorflow&CNN:驗證集預測與模型評價

    3.PyQt5多個GUI界面設計  
  本篇講GUI界面的設計。設計目標:實現用戶對路面裂紋快速檢測與識別,有三個界面:主界面、裂紋快速識別界面、圖像處理測試界面。mysql

- 環境配置安裝



  運行環境:Python3.六、Spyder、Qt Designer

  依賴的模塊:PyQt五、mysql等

  值得注意的是:我安裝PyQt5模塊時,按照網上方法,以下:web

pip install PyQt5
pip install PyQt5-tools

  卻發現找到Qt Designer的應用程序,(實際上是有的,在C盤的某個角落,能夠用everything小工具能夠找到)。
  因而乎,我就直接使用了PyQt5運行環境合集,內含Qt Designer(主要用來設計界面以及UI文件轉換成PY)。
  下載地址以下:

WinPyQt5.9-32bit-3.5.3.1sql

- 開始工做


1. 界面設計


  打開Qt Designer:數據庫


  能夠參照網上或書籍上關於Qt Designer的資料,簡單設計三個界面,以下:


  Qt Designer設計的文件後綴爲.ui,須要將其轉換爲.py文件。打開剛纔下載的PyQt5合集中的WinPython Command Prompt,輸入:多線程

pyuic5 -o D:\WinPyQt5.9-32bit-3.5.3.1\test\XX.py D:\WinPyQt5.9-32bit-3.5.3.1\test\XX.ui


  便可獲得界面的Python文件。app

2. 界面功能實現

2.1 主界面


  主界面功能比較簡單,主要是用戶對功能的選擇以及對該系統的瞭解。
dom

from PyQt5.QtWidgets import QMainWindow,QMessageBox,QApplication
from main_gui import Ui_MainWindow
import sys
import time
from PyQt5.QtGui import QPixmap

class MainWindow(QMainWindow):
    def __init__(self,parent = None):
        super(MainWindow,self).__init__(parent=parent)#調用父類的init
        global ui
        ui = Ui_MainWindow()
        ui.setupUi(self)
        
    def about_us(self):
        msgBox = QMessageBox(QMessageBox.NoIcon, '關於','XX的本科畢業設計')
        msgBox.setIconPixmap(QPixmap(".//icon//me3.jpg"))
        msgBox.exec()
    def function_exp(self):
        msgBox = QMessageBox(QMessageBox.NoIcon, '功能說明','')
        msgBox.exec()
    def operate_exp(self):
        msgBox = QMessageBox(QMessageBox.NoIcon, '操做說明','')
        msgBox.exec()

    def jump_to_1(self):
        pass

    def jump_to_2(self):   
        pass
        
    def closeEvent(self, event):
        reply = QMessageBox.question(self, '提醒',
            "肯定退出?", QMessageBox.Yes |
            QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore() 
if __name__ == '__main__':    
    app = 0
    app = QApplication(sys.argv)
    myMainWindow = MainWindow()#自定義的類例化
    myMainWindow.show()
    time.sleep(10)
    sys.exit(app.exec_())


  而對於轉換的主界面的py代碼(注意:本文將轉換成的.py文件命名爲xx_gui.py,而其對應的.py文件命名爲xx_win.py),找到以下語句:ide

self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


  修改成:svg

self.retranslateUi(MainWindow)
        self.crack_info.triggered.connect(MainWindow.jump_to_1)
        self.img_processing.triggered.connect(MainWindow.jump_to_2)
        self.function_exp.triggered.connect(MainWindow.function_exp)
        self.operate_exp.triggered.connect(MainWindow.operate_exp)
        self.about_us.triggered.connect(MainWindow.about_us)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


  這樣,主界面功能就實現了。

2.2 裂紋快速識別界面


  現已經利用CNN以及圖像處理技術實現了對裂紋的識別與檢測。這裏主要是怎麼將結果顯示在界面上。這裏參照了博客使用PyQt5建立帶文件對話框和文本對話框的ui窗口程序

from PyQt5.QtWidgets import (QMainWindow,QApplication,QFileDialog)
from PyQt5 import QtCore
from crack_detect_gui import Ui_MainWindow2
from prediction import prediction
import sys
import threading
import time
from img_processing import img_processing
import numpy as np
from mysql_save import save_mysql

class MainWindow2(QMainWindow):
    _signal=QtCore.pyqtSignal(str)#自定義信號
    def __init__(self,parent = None):
        super(MainWindow2,self).__init__(parent=parent)#調用父類的init
        self.img_opened = False
        self.imgs_opened = False
        global ui
        ui = Ui_MainWindow2()
        ui.setupUi(self)
        self.mainWindow2=ui.MainWindow2
        ui.output_info.clear()
        ui.file_name.clear()
        self._signal.connect(self.print_info)
                
    def back(self):
        pass
        
    def reset(self,parent = None): 
        pass
  
    def open_file(self):
        self.img_name = QFileDialog.getOpenFileName(self,"打開","","圖片(*.jpg;*.png)")
        ui.file_name.setPlainText(self.img_name[0])
        self.img_opened = True  
    def open_files(self):
        self.imgs_name = QFileDialog.getOpenFileNames(self,"打開","","多個圖片(*.jpg;*.png)")
        imgs_name=''
        for img_name in self.imgs_name[0]:
            imgs_name=imgs_name+img_name+'\n'
        ui.file_name.setPlainText(imgs_name)
        self.imgs_opened = True
    def print_info(self,pri_str):
        ui.output_info.appendPlainText(pri_str)
        ui.output_info.show()
        

def output_info_thread(myMainWindow):
    t1=time.time()
    Opened = False
    while(True):
        if myMainWindow.img_opened==True:
            imgs_path = myMainWindow.img_name[0].replace("/","//")
            break
        elif myMainWindow.imgs_opened==True:
            imgs_path=[]
            for path in myMainWindow.imgs_name[0]:
                imgs_path.append(path.replace("/","//"))
            break 
    Opened = True
    myMainWindow._signal.emit("當前線程:%s" %threading.current_thread().name)
    timeArray = time.localtime(t1)
    now=time.strftime("%Y_%m_%d", timeArray)
    try:
        if(Opened):
            s1 = "正在進行裂紋識別評估"
            myMainWindow._signal.emit(s1)
            kinds=prediction(imgs_path)
            s2='裂紋圖片 裂紋類型 裂紋長度 裂紋面積 裂紋最大寬度 裂紋最小寬度 裂紋平均寬度'
            myMainWindow._signal.emit(s2)
            data= np.empty(shape=[0, 8])
            for i in range(len(kinds)):
                if len(kinds)==1:
                    name=imgs_path[::-1].split('//', 1)[0][::-1]
                else:
                    name=imgs_path[i][::-1].split('//', 1)[0][::-1]
                if kinds[i]=='無裂紋':
                    crack_info=[imgs_path[i],kinds[i],'','','','']
                elif len(kinds)==1:
                    crack_info=img_processing(imgs_path,kinds[i])
                else:
                    crack_info=img_processing(imgs_path[i],kinds[i])
                s=name+' '+crack_info[0]+' '*5+crack_info[1]+' '*7+crack_info[2]+\
                ' '*11+crack_info[3]+' '*12+crack_info[4]+' '*12+crack_info[5]
                myMainWindow._signal.emit(s)
                new_crack_info=[name,crack_info[0],crack_info[1],crack_info[2],
                                crack_info[3],crack_info[4],crack_info[5],now]
                data=np.append(data, [new_crack_info], axis = 0)
            t2=time.time()
            database='crack_info'
            try:
                save_mysql(database,data)
                myMainWindow._signal.emit('數據已存入'+database+'數據庫中')
            except:
                myMainWindow._signal.emit('數據存儲失敗,請檢查數據庫是否打開!')
            time_comsume=round(t2-t1,2)
            myMainWindow._signal.emit('共耗時: '+str(time_comsume)+' s')
            myMainWindow._signal.emit("****************處理完畢****************")
    except BaseException as e1:
        print(e1)
    except EnvironmentError as e2:
        print(e2)
    except (OSError,WindowsError,
            MemoryError,NameError,
            UnboundLocalError,ReferenceError,
            RuntimeError,NotImplementedError,
            UnicodeDecodeError,UnicodeEncodeError,
            UnicodeError,UnicodeTranslateError,
            RuntimeWarning,UserWarning) as e3:
        print(e3)   

if __name__ == '__main__':
    
    app = 0
    if not QApplication.instance():
        app = QApplication(sys.argv)
    else:
        app = QApplication.instance()
    
    myMainWindow = MainWindow2()#自定義的類例化
    myMainWindow.show()

    t1 = threading.Thread(target = output_info_thread, args = (myMainWindow,))
    t1.start()
    time.sleep(10)
    sys.exit(app.exec_())


  同理,將該界面的XX_gui.py修改成:

self.retranslateUi(MainWindow2)
        self.pushButton.clicked.connect(MainWindow2.open_file)
        self.pushButton_2.clicked.connect(MainWindow2.open_files)
        self.pushButton_3.clicked.connect(MainWindow2.reset)
        self.pushButton_4.clicked.connect(MainWindow2.back)
        QtCore.QMetaObject.connectSlotsByName(MainWindow2)
        self.MainWindow2=MainWindow2
        mainWindow2=self.MainWindow2

2.3 圖像處理測試界面

import sys
from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QFileDialog,QWidget
#from img_pro_gui_code import Ui_Dialog
from img_pro_gui import Ui_Dialog
from img_processing_plot import img_processing
#from main_win import MainWindow
class Picture(QWidget):
    def __init__(self):
        super(Picture,self).__init__()#調用父類的init
        global ui
        ui = Ui_Dialog()
        ui.setupUi(self)
        self.imgs_data=ui.imgs_data
        self.dialog=ui.dialog
    def reset(self):
        pass
    def back(self):
        pass

    def open_file(self):
        imgName, imgType = QFileDialog.getOpenFileName(self, "打開圖片", "", "*.jpg;;*.png;;All Files(*)")
        self.path=imgName        
        img_path=self.path.replace("/","//")
        imgs=img_processing(img_path)
        for i in range(len(imgs)):
            jpg = QtGui.QPixmap(imgs[i]).scaled(self.imgs_data[i].width(), 
                                self.imgs_data[i].height())
            self.imgs_data[i].setPixmap(jpg)

if __name__ == "__main__":
    app=0
    app = QtWidgets.QApplication(sys.argv)
    my = Picture()
    my.show()
    sys.exit(app.exec_())


  值得一提的是,這裏的多圖片顯示功能,我是先將圖像處理測試程序中產生的圖片保存到本地再使用QPixmap方法導入並顯示。

  同理,該界面所對應的XX_gui.py文件中改寫爲:

self.retranslateUi(Dialog)
        self.choose.clicked.connect(Dialog.open_file)
        self.clear.clicked.connect(Dialog.reset)
        self.back.clicked.connect(Dialog.back)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
        self.imgs_data=[self.img_source,self.img_blur,self.img_canny,self.img_cut,
               self.img_close,self.img_open,self.img_domain,self.img_skeleton]
        imgs_data=self.imgs_data
        self.dialog=Dialog
        dialog=self.dialog

3. 界面跳轉與重置

3.1主界面與裂紋快速識別界面


  主界面跳轉界面1修改成:

def jump_to_1(self):
        #myMainWindow.hide() #若是沒有這一句,關閉子界面後就會關閉程序
        self.ui_1=MainWindow2()
        self.ui_1.show()
        crack_detect(self.ui_1)


  裂紋快速識別界面上返回功能是直接關閉當前界面,重置功能是將界面數據清零並再次啓動多線程。

def back(self):
        self.mainWindow2.close()
        
    def reset(self,parent = None): 
        self.img_opened = False
        self.imgs_opened = False
        ui.output_info.clear()
        ui.file_name.clear()
        t1 = threading.Thread(target = output_info_thread, args = (myMainWindow,))
        t1.start()

3.2主界面與圖像處理測試界面


  主界面跳轉界面2修改成:

def jump_to_2(self):   
        #myMainWindow.hide() #若是沒有這一句,關閉子界面後就會關閉程序
        self.ui_2=Picture()
        self.ui_2.show()


  圖像處理測試界面上返回功能的實現同上,重置功能是將界面數據清零。

def reset(self):
        for label in self.imgs_data:
            label.clear()
    def back(self):
        self.dialog.close()

- 結果展現



  在命令行運行主界面程序,結果以下(以Gif展現):
在這裏插入圖片描述

- 寫在最後


  因爲時間有限且初次設計GUI界面(經驗不足),界面比較醜,請見諒。如有問題,歡迎留言。

相關文章
相關標籤/搜索