簡體   English   中英

如何在 PyQT5 中暫停/播放線程?

[英]How to pause/play a thread in PyQT5?

我正在用 PyQT5 制作一個輕量級的 GUI 程序。

但是現在我面臨着一些關於線程的問題。

我只是做了一個簡單的測試程序,比如底部:

該程序只是試圖將數字附加到文本框,但它崩潰了。

我不知道為什么但不知何故我可以通過刪除評論來防止它(time.sleep)

import sys
import threading
import time
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class Some(QWidget):
    e = threading.Event()

    def btnfunc(self):
        self.e.set()        

    def __init__(self):
        super().__init__()
        self.myButton = QPushButton('do next')
        self.logs = QTextEdit()

        self.mylay = QVBoxLayout()
        self.mylay.addWidget(self.myButton)
        self.mylay.addWidget(self.logs)

        self.setLayout(self.mylay)
        self.setGeometry(300, 300, 300, 550)
        self.setWindowTitle('mytest')
        self.show()
        t = threading.Thread(target=self.myfunc, args=( ))
        t.start()
        self.myButton.clicked.connect(self.btnfunc)

    def myfunc(self):
        for i in range(300):
            # time.sleep(0.4)
            self.logs.append(str(i))
            if i == 20:
                self.e.wait()

app = QApplication(sys.argv)
ex = Some()
sys.exit(app.exec_())

如果時間設置得高一些會更好。

我認為這是因為資源訪問,因為它是pyQT5 GUI。

所以我找到了 QThread。 我試着像底部一樣,

import sys
import time
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class Some(QWidget):
    qw = QWaitCondition()
    qm = QMutex()

    def btnfunc(self):
        self.qw.wakeAll()

    def __init__(self):
        super().__init__()
        self.myButton = QPushButton('do next')
        self.logs = QTextEdit()

        self.mylay = QVBoxLayout()
        self.mylay.addWidget(self.myButton)
        self.mylay.addWidget(self.logs)

        self.setLayout(self.mylay)
        self.setGeometry(300, 300, 300, 550)
        self.setWindowTitle('mytest')
        self.show()    
        self.myButton.clicked.connect(self.btnfunc)

        self.thread = QThread()
        self.thread.started.connect(self.myfunc)
        self.thread.start()

    def myfunc(self):
        for i in range(300):
            self.logs.append(str(i))
            if i == 20:
                self.qw.wait(self.qm)

app = QApplication(sys.argv)
ex = Some()
sys.exit(app.exec_())

但崩潰,不起作用。 並嘗試了 QThread+threading.Event()。 它凍結了 GUI。

現在不知道怎么處理了...

編輯:我剛剛意識到線程。 不應從除 QThread 之外的其他線程訪問。 然后我會繼續查找 QWaitCondition

您不應該通過多線程直接控制 GUI。 由於兩個不同的線程試圖控制 GUI,這會導致凍結或崩潰。 我從這里了解了這個概念http://www.xyzlang.com/python/PyQT5/pyqt_multithreading.html

這是您可以完美運行的代碼。

import sys
import threading
import time
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

# Added new
class Communicate(QObject):
    signal = pyqtSignal(str)

class Some(QWidget):
    e = threading.Event()

    def btnfunc(self):
        self.e.set()        

    def __init__(self):
        super().__init__()

        #communicate object
        self.comm = Communicate()
        self.comm.signal.connect(self.append_data)

        self.myButton = QPushButton('do next')
        self.logs = QTextEdit()

        self.mylay = QVBoxLayout()
        self.mylay.addWidget(self.myButton)
        self.mylay.addWidget(self.logs)

        self.setLayout(self.mylay)
        self.setGeometry(300, 300, 300, 550)
        self.setWindowTitle('mytest')
        self.show()
        t = threading.Thread(target=self.myfunc, args=( ))
        t.start()
        self.myButton.clicked.connect(self.btnfunc)

    def myfunc(self):
        for i in range(300):
            # time.sleep(0.4)
            #self.logs.append(str(i))
            self.comm.signal.emit(str(i))
            if i == 20:
                self.e.wait()

    def append_data(self, data):
        self.logs.append(data)

app = QApplication(sys.argv)
ex = Some()
sys.exit(app.exec_())

您可以使用 while = True 暫停循環,也可以使用 break 語句停止循環

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import (
    Qt, QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool
)
import time
from time import sleep
import threading

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(655, 589)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.run = QtWidgets.QPushButton(self.centralwidget)
        self.run.setGeometry(QtCore.QRect(260, 50, 93, 28))
        self.run.setObjectName("run")
        self.result = QtWidgets.QTextEdit(self.centralwidget)
        self.result.setGeometry(QtCore.QRect(110, 120, 491, 201))
        self.result.setObjectName("result")
        self.stop = QtWidgets.QPushButton(self.centralwidget)
        self.stop.setGeometry(QtCore.QRect(110, 390, 93, 28))
        self.stop.setObjectName("stop")
        self.pause = QtWidgets.QPushButton(self.centralwidget)
        self.pause.setGeometry(QtCore.QRect(300, 390, 93, 28))
        self.pause.setObjectName("pause")
        self.resume = QtWidgets.QPushButton(self.centralwidget)
        self.resume.setGeometry(QtCore.QRect(480, 390, 93, 28))
        self.resume.setObjectName("resume")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 655, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        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", "MainWindow"))
        self.run.setText(_translate("MainWindow", "Run"))
        self.stop.setText(_translate("MainWindow", "stop"))
        self.pause.setText(_translate("MainWindow", "Pause"))
        self.resume.setText(_translate("MainWindow", "Resume"))
        
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.is_paused = False
        self.is_killed = False
        self.run.clicked.connect(self.send_wala)
        self.stop.clicked.connect(self.kill_g)
        self.pause.clicked.connect(self.pause_g)
        self.resume.clicked.connect(self.resume_g)
        
    @QtCore.pyqtSlot()
    def send_wala(self):
        threading.Thread(target=self.working, daemon=True).start()
        
        
    def working(self):
        for i in range(10):
            sleep(3)
            self.result.append(str(i))
            while self.is_paused:
                time.sleep(0)
                
            if self.is_killed:
                break
            
    def pause_g(self):
        self.is_paused = True
        
    def resume_g(self):
        self.is_paused = False
        
    def kill_g(self):
        self.is_killed = True
        


import sys

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM