少妇脱了内裤让我添,久久久久亚洲精品无码网址蜜桃,性色av免费观看,久久人妻av无码中文专区

分享

PySide6————多線程技術(QTimer、QThread、事件處理)

 ly88 2024-12-16


不要停止呼吸已于 2023-10-23 21:47:09 修改

GUI程序中,單線程常常滿足不了需求。這是因為,當程序需要執行一個非常耗時的操作(例如渲染、大量計算、數據傳輸等操作),那么整個界面則可能出現無法交互的情況(這是非常糟糕的現象,想象一下,你想點擊一下按鈕,可是鼠標卻一直是轉圈圈的狀態)

一般來說,多線程技術涉及三種方法:

  • 計時器模塊QTimer;

  • 多線程模塊QThread;

  • 事件處理

QTimer計時器

當我們要周期性進行某項操作時(如定時發送數據,定時獲取傳感器數據),則可以使用定時器QTimer,該類提供了重復定時器和單次定時器。

可以在具有事件循環的線程中使用 QTimer;要在非GUI線程啟動事件循環,可以使用 exec() 。Qt使用計時器的 ”線程相關性“ 來確定哪一個線程發出 timeout() 信號,因而必須在該線程中開啟和關閉計時器,而不能從另一個線程啟動或關閉。

==作為一種特殊情況,超時為0的QTimer將盡快超時,即盡快反復執行(一旦處理完窗口系統的事件隊列中的所有事件,超時間隔為0的QTimer就會超時)。==這種情況下槽函數代碼應該很簡單,能夠快速返回,并在完成所有工作后立即停止計時器。這是在GUI程序中實現繁重工作的傳統方式,但隨著多線程的廣泛使用,零毫秒計時器將被 QThread 代替。

計時器的精確度取決于底層操作系統和硬件。大多數平臺支持1毫秒的分辨率,盡管在許多現實世界的情況下,計時器的精度不會等于這個分辨率。如果系統繁忙或無法提供所要求的精度,則所有類型的計時器都可能比預期的晚超時,在這種超時溢出的情況下,即使多個超時已經過期,Qt也只會發出一次timeout() ,然后將恢復原始間隔。

定時器的實現依賴的是CPU時鐘中斷,時鐘中斷的精度就決定定時器精度的極限。一個時鐘中斷源如何實現多個定時器呢?對于內核,簡單來說就是用特定的數據結構管理眾多的定時器,在時鐘中斷處理中判斷哪些定時器超時,然后執行超時處理動作。而用戶空間程序不直接感知CPU時鐘中斷,通過感知內核的信號、IO事件、調度,間接依賴時鐘中斷。用軟件來實現動態定時器常用數據結構有:時間輪、最小堆和紅黑樹。

另一種實現計時器的方法是繼承QObject類,并重寫 timerEvent() 事件處理器,然后調用 startTimer() 函數。具體 細節可以查看:QTimer - Qt for Python

構造函數

class PySide6.QtCore.QTimer([parent=None])
  • 1

parent – PySide6.QtCore.QObject

屬性

屬性名描述
active布爾值,計時器是否正在運行
singleShot布爾值,計時器是否為單次計時器,默認為false
intervalint類型,超時間隔,單位為毫秒。默認值為0

函數

函數名描述
start()
start(msec)
開啟計時器,如果singleShot為true,則計時器將僅激活一次。
stop()關閉計時器
timeout()計時器超時時會發出此信號

重復計時器

import sys

from PySide6.QtCore import QDateTime, QTimer
from PySide6.QtGui import Qt
from PySide6.QtWidgets import QWidget, QApplication, QLabel, QPushButton, QGridLayout


class LearnQThread(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Learn QThread')
        self.resize(640, 480)

        self.label = QLabel(self)
        self.label.setAlignment(Qt.AlignCenter)
        self.btnStart = QPushButton('start')
        self.btnEnd = QPushButton('end')
        layout = QGridLayout()
        self.timer = QTimer()

        self.timer.timeout.connect(self.showtime)

        layout.addWidget(self.label, 0, 0, 1, 2)
        layout.addWidget(self.btnStart, 1, 0)
        layout.addWidget(self.btnEnd, 1, 1)

        self.btnStart.clicked.connect(self.StartTimer)
        self.btnEnd.clicked.connect(self.endTimer)
        self.setLayout(layout)

    """
    
    QTimer定時處理的任務
    
    """

    def showtime(self):
        # 獲取當前時間
        time = QDateTime.currentDateTime()
        # 將當前時間轉換成字符串類型
        timeDisplay = time.toString('yyyy-MM-dd hh:mm:ss dddd')

        self.label.setText(timeDisplay)

    def StartTimer(self):
        # 開啟定時器,執行時間/任務的頻率是100ms
        self.timer.start(100)
        self.btnStart.setEnabled(False)
        self.btnEnd.setEnabled(True)

    def endTimer(self):
        self.timer.stop()
        self.label.clear()
        self.btnStart.setEnabled(True)
        self.btnEnd.setEnabled(False)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    wid = LearnQThread()
    wid.show()
    sys.exit(app.exec())
  • 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

單次計時器

import sys
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QApplication, QWidget, QLabel,QGridLayout


class LearnQTimer(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(320,240)
        self.label = QLabel(self)
        layout = QGridLayout()
        layout.addWidget(self.label)
        self.setLayout(layout)
        self.label.setText('close ui')
        self.label.setAlignment(Qt.AlignCenter)
        QTimer.singleShot(5000, self.close)			# 5秒后自動關閉窗口


if __name__ == '__main__':
    app = QApplication(sys.argv)
    wid = LearnQTimer()
    wid.show()
    sys.exit(app.exec())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

QThread多線程

QThread類提供了一種獨立于平臺的方式來管理線程。

QThread 在 run() 中開始執行。默認情況下,run() 通過調用exec() 啟動事件循環,并在線程內運行Qt事件循環

構造函數

class PySide6.QtCore.QThread([parent=None])
  • 1

parent – PySide6.QtCore.QObject

在調用start() 之前,線程不會開始執行。

函數

函數名描述
exec()run() 會調用此函數,有必要調用此函數來啟動事件處理。這只能在線程本身內調用,即當它是當前線程時。
exit([retcode=0])線程的事件循環退出并返回一個int型整數。
finished()當發出此信號時,事件循環已經停止運行,線程中將不再處理任何事件。這個信號可以連接到deleteLater(),以釋放該線程中的對象。
run()在調用 start() 之后,新創建的線程將自動調用此函數。默認實現只調用exec()
start([priority=QThread.Priority.InheritPriority])內部通過調用 run() 開始執行線程
started()執行 run() 之前發出此信號
import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *

global sec
sec = 0


class WorkThread(QThread):
    trigger = Signal()


    def __int__(self):
        super(WorkThread, self).__init__()

    def run(self):
        for i in range(2000000000):
            pass

        # 循環完畢后發出信號
        self.trigger.emit()


def countTime():
    global sec
    sec += 1
    # LED顯示數字+1
    lcdNumber.display(sec)


def work():
    # 計時器每秒計數
    timer.start(1000)
    # 計時開始
    workThread.start()
    # 當獲得循環完畢的信號時,停止計數
    workThread.trigger.connect(timeStop)


def timeStop():
    timer.stop()
    print("運行結束用時", lcdNumber.value())
    global sec
    sec = 0


if __name__ == "__main__":
    app = QApplication(sys.argv)
    top = QWidget()
    top.resize(300, 120)

    # 垂直布局類QVBoxLayout
    layout = QVBoxLayout(top)
    # 加個顯示屏
    lcdNumber = QLCDNumber()
    layout.addWidget(lcdNumber)
    button = QPushButton("測試")
    layout.addWidget(button)

    timer = QTimer()
    workThread = WorkThread()

    button.clicked.connect(work)
    # 每次計時結束,觸發 countTime
    timer.timeout.connect(countTime)

    top.show()
    sys.exit(app.exec_())
  • 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
  • 66
  • 67
  • 68
  • 69

事件處理

PyQt為事件處理提供了兩種機制:高級的信號與槽機制以及低級的事件處理程序。本篇文博只介紹低級的事件處理程序即:processEvents()函數的使用方法,它的作用是處理事件,簡單地說,就是刷新頁面。

對于執行很耗時的程序來說,由于PyQt需要等待程序執行完畢才能進行下一步,這個過程表現在界面上就是卡頓。而如果在執行這個耗時程序時不斷地運行 QApplication.processEvents(),那么就可以實現一邊執行耗時程序,一邊刷新頁面的功能,給人的感覺就是程序運行很流暢。

因此QApplication.processEvents()的使用方法就是,在主函數執行耗時操作的地方,加入QApplication.processEvents()。

from PySide6.QtWidgets import QWidget, QPushButton, QApplication, QListWidget, QGridLayout
import sys
import time


class WinForm(QWidget):

    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.setWindowTitle("實時刷新界面例子")
        self.listFile = QListWidget()
        self.btnStart = QPushButton('開始')
        layout = QGridLayout(self)
        layout.addWidget(self.listFile, 0, 0, 1, 2)
        layout.addWidget(self.btnStart, 1, 1)
        self.btnStart.clicked.connect(self.slotAdd)
        self.setLayout(layout)

    def slotAdd(self):
        for n in range(10):
            str_n = 'File index {0}'.format(n)
            self.listFile.addItem(str_n)
            QApplication.processEvents()
            time.sleep(1)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = WinForm()
    form.show()
    sys.exit(app.exec_())
  • 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

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發表

    請遵守用戶 評論公約

    類似文章 更多

    主站蜘蛛池模板: 欧美交换配乱吟粗大免费看| 欧美黑人又粗又大久久久| 亚洲中文字幕久久精品无码app| 在线va无码中文字幕| 国产免费无遮挡吸奶头视频| 亚洲aⅴ无码成人网站国产| 国产亚洲精品久久久久久床戏| 国产在线码观看超清无码视频| 婷婷丁香五月亚洲中文字幕| 午夜天堂av天堂久久久| 激情内射人妻1区2区3区| 最新精品国偷自产在线美女足| 1313午夜精品理论片| 美女扒开奶罩露出奶头视频网站| 亚洲色大成网站久久久| 99精品国产成人一区二区| 久久久久无码国产精品不卡| 国产桃色无码视频在线观看| 色综合天天综合狠狠爱_| 免费大黄网站| 538prom精品视频在线播放| 大肉大捧一进一出好爽视频mba| 人人狠狠综合久久亚洲爱咲| 国产亚洲精品久久久久久大师| 在线精品亚洲一区二区| 亚洲午夜理论片在线观看| 99国产精品人妻噜啊噜| 在线观看免费人成视频| 国产在线乱码一区二区三区| 国产女主播喷水视频在线观看| 宝宝好涨水快流出来免费视频| 精品久久久久久无码中文字幕漫画| 四虎影视永久免费观看| 成人亚洲a片v一区二区三区日本| 婷婷五月六月激情综合色中文字幕| 思思re热免费精品视频66| 亚洲爱婷婷色婷婷五月| 精品免费人成视频网| 成人无遮挡18禁免费视频| 亚洲国产三级在线观看| 四虎国产精品永久在线动漫|