最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Pyqt5實(shí)現(xiàn)多線(xiàn)程程序的使用示例

 更新時(shí)間:2023年11月23日 15:53:34   作者:唐BiuBiu  
Pyqt常常使用主從架構(gòu)(Master-Workers 架構(gòu))來(lái)避免界面卡死的情況,本文主要介紹了Pyqt5實(shí)現(xiàn)多線(xiàn)程程序的使用示例,感興趣的可以了解一下

主從架構(gòu)

Pyqt常常使用**主從架構(gòu)(Master-Workers 架構(gòu))**來(lái)避免界面卡死的情況。

Master-Workers 架構(gòu)就像它的名字,一個(gè)master統(tǒng)領(lǐng)著幾個(gè)workers一起干活。其中某個(gè)worker倒下了不會(huì)導(dǎo)致整體任務(wù)失敗。matser不用干活,因此可以專(zhuān)心指揮workers。

在qt5中,master代表主線(xiàn)程,主要維持主界面的運(yùn)行。當(dāng)觸發(fā)某項(xiàng)耗時(shí)耗力的任務(wù)時(shí),主線(xiàn)程將這項(xiàng)任務(wù)分配給其他線(xiàn)程(workers)來(lái)做。其他線(xiàn)程出現(xiàn)了災(zāi)難性的錯(cuò)誤,不會(huì)影響到主線(xiàn)程,因此程序不會(huì)完全崩潰。且主線(xiàn)程不承擔(dān)耗時(shí)耗力的任務(wù),因此避免了復(fù)雜運(yùn)算時(shí)主界面卡頓的問(wèn)題。

進(jìn)程和線(xiàn)程詳見(jiàn)1

pyqt5多線(xiàn)程的架構(gòu)一般由三個(gè)模塊實(shí)現(xiàn):

  • Gui.py:只存放GUI界面,一般是Qt Designer生成的代碼,無(wú)需做任何修改
  • Thread.py:從線(xiàn)程,主要的邏輯代碼都放在這里。接收主線(xiàn)程的指令,并向主線(xiàn)程返回信號(hào)。
  • Main.py:主線(xiàn)程,負(fù)責(zé)運(yùn)行GUI界面,向從線(xiàn)程發(fā)送指令并接收從線(xiàn)程返回的信號(hào)。

GUI模塊

Qt Designer保存的文件為Gui.ui的格式,使用下面命令轉(zhuǎn)為Gui.py。

pyuic5 Gui.ui -o Gui.py

轉(zhuǎn)換后的代碼結(jié)構(gòu)如下,我們不需要對(duì)這個(gè)代碼做任何修改。

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.5.1
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object): # 注意這個(gè)類(lèi)名,后面在Main.py中找到它
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        # ------- 省略很多行... ------- #
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "標(biāo)題"))
        # ------- 省略很多行... ------- #

不同線(xiàn)程間的信號(hào)與槽

在討論主線(xiàn)程和從線(xiàn)程之前,首先要明確線(xiàn)程間傳遞信號(hào)的方法2。

主 -> 從

主線(xiàn)程到從線(xiàn)程的信號(hào)就是最基本信號(hào)與槽的機(jī)制,使用槽函數(shù)來(lái)與從線(xiàn)程通信。一般是Wight被clicked,然后觸發(fā)槽函數(shù)。傳遞的路徑為:1.觸發(fā)信號(hào)事件 -> 2.信號(hào)clicked -> 3.槽函數(shù)接收信號(hào)并運(yùn)行。使用以下語(yǔ)句綁定槽函數(shù):

from Thread import New_thread # 從線(xiàn)程的引用

class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None) -> None:
        super(MainWindow,self).__init__(parent)
        self.setupUi(self)
        
        # ----------------------------------------- #
        # ↓↓↓↓↓↓↓ 不用管上面的代碼,主要看下面 ↓↓↓↓↓↓↓ #
        # ----------------------------------------- #
        
        self.thread = None # 先預(yù)定義一個(gè)從線(xiàn)程的實(shí)例屬性,這里無(wú)需將從線(xiàn)程實(shí)例化
        # self.btn為Ui_MainWindow中定義的按鈕,這里將按鈕點(diǎn)擊的信號(hào)與槽函數(shù)self.func連接起來(lái)
        self.btn.clicked.connect(self.func) 

    def func(self):
        self.thread = New_thread() # 在槽函數(shù)中實(shí)例化從線(xiàn)程,然后就可以操作從線(xiàn)程了
        self.thread.start()
        pass

有時(shí)我們需要向槽函數(shù)傳遞參數(shù),一般使用偏函數(shù)或lambda,偏函數(shù)可參見(jiàn)3

from functools import partial # 偏函數(shù)的引用
from Thread import New_thread # 從線(xiàn)程的引用

class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None) -> None:
        super(MainWindow,self).__init__(parent)
        self.setupUi(self)
        
        # ----------------------------------------- #
        # ↓↓↓↓↓↓↓ 不用管上面的代碼,主要看下面 ↓↓↓↓↓↓↓ #
        # ----------------------------------------- #
        
        self.thread = None # 先預(yù)定義一個(gè)從線(xiàn)程的實(shí)例屬性,這里無(wú)需將從線(xiàn)程實(shí)例化
        # 第一種方法:這個(gè)槽函數(shù)被寫(xiě)成了偏函數(shù)的形式 partial(self.func, param1, param2)
	    self.btn1.clicked.connect(partial(self.func, param1=1, param2=2)) 
        # 第二種方法:這個(gè)槽函數(shù)被寫(xiě)成了lambda的形式 lambda:self.func(param1=1, param2=2)
        self.btn2.clicked.connect(lambda:self.func(param1=1, param2=2))
        
    # 這個(gè)槽函數(shù)監(jiān)聽(tīng)了兩個(gè)信號(hào)哦
    def func(self, param1, param2):
         # 在槽函數(shù)中實(shí)例化從線(xiàn)程,然后就可以操作從線(xiàn)程了
        self.thread = New_thread(param1, param2) # 從線(xiàn)程實(shí)例化也可以放在__init__里面,但我喜歡放在這。
        self.thread.start()
        pass

從 -> 主

從線(xiàn)程向主線(xiàn)程傳遞信號(hào)一般使用自定義信號(hào),觸發(fā)后,從線(xiàn)程的自定義信號(hào)傳遞給主線(xiàn)程連接的槽函數(shù)。觸發(fā)的路徑為1.從線(xiàn)程觸發(fā)信號(hào)emit -> 2.聲明信號(hào)pyqtSignal -> 3.傳遞給主線(xiàn)程連接的槽函數(shù)。使用下面代碼建立自定義信號(hào)。

先在Thread.py中定義信號(hào):

# Thread.py
from PyQt5.QtCore import QThread, pyqtSignal

class New_Thread(QThread):
    # 聲明定義信號(hào),注意它必須是類(lèi)屬性。
    mySignal = pyqtSignal(int,str) # 后面的參數(shù)是信號(hào)的數(shù)據(jù)類(lèi)型
    
    def __init__(self) -> None:
        super(New_Thread, self).__init__(parent)
        pass 
    
    def run(self):
        pass
    
    # ------------------------------------------ #
    # ↓↓↓↓↓↓↓ 上面的兩個(gè)函數(shù)不用理會(huì),看下面 ↓↓↓↓↓↓↓ #
    # ------------------------------------------ #
    
    # 下面是從線(xiàn)程的邏輯代碼
    def func(self):
        # ------- 省略很多邏輯代碼... ------- #
        # 向主線(xiàn)程發(fā)送信號(hào)
        self.mySignal.emit(1,"Hello, Pyqt5")

在主線(xiàn)程Main.py中監(jiān)聽(tīng)信號(hào)并連接到槽:

# Main.py
from Thread import New_thread # 從線(xiàn)程的引用

class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None) -> None:
        super(MainWindow,self).__init__(parent)
        self.setupUi(self)
        
        # ----------------------------------------- #
        # ↓↓↓↓↓↓↓ 不用管上面的代碼,主要看下面 ↓↓↓↓↓↓↓ #
        # ----------------------------------------- #
        
    def func1(self):
        self.thread = New_thread() # 從線(xiàn)程實(shí)例化(也可以放在__init__里面)
        self.thread.start()
        # 監(jiān)聽(tīng)從線(xiàn)程發(fā)出的信號(hào),并連接到槽函數(shù)func2
        # 記得嗎?mySignal發(fā)出了兩個(gè)數(shù)據(jù),一個(gè)是int類(lèi)型,一個(gè)str類(lèi)型
        self.thread.mySignal.connect(self.func2) 
    
    # 槽函數(shù)接收了從線(xiàn)程的信號(hào)
    def func2(self, param1:int, param2:str):
        pass

主線(xiàn)程Main模塊

主線(xiàn)程的作用是維護(hù)UI界面運(yùn)行,下面給出Main模塊的一般架構(gòu)

import sys # 顯示ui界面必要的引用
from PyQt5.QtWidgets import QMainWindow, QApplication # 顯示ui界面必要的引用
from GUI import * # 引用Qt Designer生成的GUI模塊
from Thread import New_thread # 從線(xiàn)程的引用

# 第一個(gè)父類(lèi)是PyQt5.QtWidgets.QMainWindow(取決于你在Qt Designer選擇的窗口類(lèi)型)
# 第二個(gè)父類(lèi)是GUI.Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow): 

    def __init__(self, parent=None) -> None:
        super(MainWindow,self).__init__(parent)
        self.setupUi(self) # 初始化UI界面
        self.thread = None # 先預(yù)定義一個(gè)從線(xiàn)程的實(shí)例屬性,這里無(wú)需將從線(xiàn)程實(shí)例化
        self.btn1.clicked.connect(self.func1) # 綁定控件的槽函數(shù),以啟動(dòng)從線(xiàn)程
        self.thread.finished.connect(self.func3) # 監(jiān)聽(tīng)線(xiàn)程是否完成任務(wù),以結(jié)束從線(xiàn)程
        # 省略一萬(wàn)行綁定槽函數(shù)的代碼...
        
    # 定義槽函數(shù),這里可以放入從線(xiàn)程。
    def func1(self):
        self.thread = New_Thread() # 實(shí)例化一個(gè)從函數(shù)
        self.thread.start()
        self.thread.mySignal.connect(self.func2) # 監(jiān)聽(tīng)從線(xiàn)程的信號(hào),并綁定槽函數(shù)
    
    # 定義響應(yīng)從線(xiàn)程信號(hào)的槽函數(shù)
    def func2(self,param:int):
        pass
    
    # 定義結(jié)束從線(xiàn)程的槽函數(shù)
    def func3(self):
        self.thread.stop()
    
    # 省略一萬(wàn)個(gè)槽函數(shù)...

if __name__ == '__main__':
    # 任何一個(gè)qt應(yīng)用都必須有且僅有一個(gè)QApplication對(duì)象
    # sys.argv是一組命令行參數(shù)的列表。
    # 這行代碼就是實(shí)例化一個(gè)QApplication
    app = QApplication(sys.argv) 
    
    # 主線(xiàn)程實(shí)例化
    main_window = MainWindow()
    
    # 顯示窗口
    main_window.show()
    
    # sys.exit()是Python退出進(jìn)程的函數(shù)
    # QApplication.exec_()的功能是“qt程序進(jìn)入主循環(huán),直到exit()被調(diào)用”
    # 沒(méi)有exec_()的話(huà),程序不會(huì)進(jìn)入主循環(huán),會(huì)閃退。沒(méi)有sys.exit()的話(huà),程序退出后進(jìn)程不會(huì)結(jié)束。
    sys.exit(app.exec_())

從線(xiàn)程Thread模塊

from PyQt5.QtCore import QThread, pyqtSignal
from functools import partial

class New_Thread(QThread):
    # 聲明定義信號(hào),注意它必須是類(lèi)屬性。
    mySignal = pyqtSignal(int,str) # 后面的參數(shù)是信號(hào)的數(shù)據(jù)類(lèi)型
    finishedSignal = pyqtSignal() # 線(xiàn)程完成的信號(hào)
    
    def __init__(self) -> None:
        super(New_Thread, self).__init__(parent)
    
    # run()是父類(lèi)的方法,這里要重寫(xiě)run方法
    # 將邏輯代碼放在run里面,當(dāng)主線(xiàn)程調(diào)用thead.start()時(shí)會(huì)自動(dòng)運(yùn)行run函數(shù)。
    def run(self):
        # 省略一萬(wàn)行代碼
        self.finishedSignal.emit()
    
    # 停止線(xiàn)程
    def stop(self):
        self.isRunning = False # isRunning是父類(lèi)的屬性,可以停止線(xiàn)程。

參考文章

到此這篇關(guān)于Pyqt5實(shí)現(xiàn)多線(xiàn)程程序的使用示例的文章就介紹到這了,更多相關(guān)Pyqt5多線(xiàn)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • javascript實(shí)現(xiàn)的textarea運(yùn)行框效果代碼 不用指定id批量指定

    javascript實(shí)現(xiàn)的textarea運(yùn)行框效果代碼 不用指定id批量指定

    今天在寫(xiě)一個(gè)網(wǎng)頁(yè)的時(shí)候用到了N多嵌套在textarea標(biāo)簽里的代碼,定義雙擊運(yùn)行其內(nèi)的代碼段。但是每次創(chuàng)建一個(gè)這樣的可運(yùn)行的實(shí)例都要給textarea元素自定義一個(gè)id值和寫(xiě)入雙擊事件,好不麻煩。
    2009-12-12
  • 微信小程序使用map組件實(shí)現(xiàn)解析經(jīng)緯度功能示例

    微信小程序使用map組件實(shí)現(xiàn)解析經(jīng)緯度功能示例

    這篇文章主要介紹了微信小程序使用map組件實(shí)現(xiàn)解析經(jīng)緯度功能,涉及微信小程序map組件結(jié)合高德地圖進(jìn)行經(jīng)緯度獲取相關(guān)操作技巧,需要的朋友可以參考下
    2019-01-01
  • 微信小程序全局配置以及頁(yè)面配置詳解

    微信小程序全局配置以及頁(yè)面配置詳解

    微信小程序中我們創(chuàng)建頁(yè)面時(shí)會(huì)自動(dòng)創(chuàng)建四個(gè)文件分別為js文件,wxml文件wxss文件最后還有我們今天的主角json配置文件,下面這篇文章主要給大家介紹了關(guān)于微信小程序全局配置以及頁(yè)面配置的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • JS+CSS繪制棋盤(pán)格的示例代碼

    JS+CSS繪制棋盤(pán)格的示例代碼

    在這篇文章中,將為大家展示如何使用css Flex-box和一些JavaScript來(lái)設(shè)計(jì)棋盤(pán)。文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-05-05
  • 解析Javascript中難以理解的11個(gè)問(wèn)題

    解析Javascript中難以理解的11個(gè)問(wèn)題

    這篇文章主要是對(duì)Javascript中難以理解的11個(gè)問(wèn)題進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-12-12
  • 十分鐘教你上手ES2020新特性

    十分鐘教你上手ES2020新特性

    這篇文章主要介紹了十分鐘教你上手ES2020新特性,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 解決layer.open彈出框不能獲取input框的值為空的問(wèn)題

    解決layer.open彈出框不能獲取input框的值為空的問(wèn)題

    今天小編就為大家分享一篇解決layer.open彈出框不能獲取input框的值為空的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-09-09
  • 詳解javascript事件冒泡

    詳解javascript事件冒泡

    這篇文章主要向大家介紹了javascript事件冒泡,以及javascript阻止事件冒泡的實(shí)現(xiàn)代碼,感興趣的朋友可以參考一下
    2016-01-01
  • JavaScript語(yǔ)法 JSON序列化之stringify實(shí)例詳解

    JavaScript語(yǔ)法 JSON序列化之stringify實(shí)例詳解

    這篇文章主要為大家介紹了JavaScript語(yǔ)法 JSON序列化之stringify實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • uniapp引入axios異步框架的完整步驟

    uniapp引入axios異步框架的完整步驟

    雖然Uniapp可以使用Vue.js自帶的$http,但也可以使用Axios,只需要在項(xiàng)目中進(jìn)行簡(jiǎn)單的配置,這篇文章主要給大家介紹了關(guān)于uniapp引入axios異步框架的相關(guān)資料,需要的朋友可以參考下
    2023-12-12

最新評(píng)論

襄樊市| 体育| 霍州市| 永福县| 南乐县| 民县| 汕头市| 惠州市| 玉林市| 社旗县| 台前县| 怀宁县| 曲周县| 隆德县| 岚皋县| 盐池县| 丰顺县| 武川县| 伊宁市| 八宿县| 沾化县| 陵川县| 绵阳市| 黄冈市| 崇礼县| 理塘县| 龙口市| 台东县| 凤凰县| 二手房| 宜黄县| 织金县| 东乌珠穆沁旗| 定襄县| 濮阳市| 山丹县| 长兴县| 呈贡县| 阿巴嘎旗| 文昌市| 竹北市|