繁体   English   中英

当我在python pyqt上关闭gui时,Qthread仍在工作

[英]Qthread is still working when i close gui on python pyqt

我的代码有线程,但是当我关闭gui时,它仍然可以在后台运行。 如何停止线程? 是否有停止(),关闭()的东西? 我不使用信号,插槽? 我必须使用这个吗?

from PyQt4 import QtGui, QtCore
import sys
import time
import threading

class Main(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.kac_ders=QtGui.QComboBox()
        self.bilgi_cek=QtGui.QPushButton("Save")
        self.text=QtGui.QLineEdit()
        self.widgetlayout=QtGui.QFormLayout()
        self.widgetlar=QtGui.QWidget()
        self.widgetlar.setLayout(self.widgetlayout)
        self.bilgiler=QtGui.QTextBrowser()
        self.bilgi_cek.clicked.connect(self.on_testLoop)
        self.scrollArea = QtGui.QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setWidget(self.widgetlar)
        self.analayout=QtGui.QVBoxLayout()
        self.analayout.addWidget(self.text)
        self.analayout.addWidget(self.bilgi_cek)
        self.analayout.addWidget(self.bilgiler)
        self.centralWidget=QtGui.QWidget()
        self.centralWidget.setLayout(self.analayout)
        self.setCentralWidget(self.centralWidget)

    def on_testLoop(self):
        self.c_thread=threading.Thread(target=self.kontenjan_ara)
        self.c_thread.start()

    def kontenjan_ara(self):

        while(1):
                self.bilgiler.append(self.text.text())
                time.sleep(10)


app = QtGui.QApplication(sys.argv)
myWidget = Main()
myWidget.show()
app.exec_()

一些东西:

  1. 您不应该从主线程之外调用GUI代码。 GUI元素不是线程安全的。 self.kontenjan_ara更新并读取GUI元素,它不应该成为您thread的目标。

  2. 在几乎所有情况下,都应使用QThreads而不是python线程。 它们与Qt中的事件和信号系统很好地集成在一起。

如果只想每隔几秒钟运行一次,则可以使用QTimer

def __init__(self, parent=None):
    ...
    self.timer = QTimer(self)
    self.timer.timeout.connect(self.kontenjan_ara)
    self.timer.start(10000)

def kontenjan_ara(self):
    self.bilgiler.append(self.text.text())

如果线程操作在计算上更加复杂,则可以创建一个工作线程,并使用信号在工作线程和主GUI线程之间传递数据。

class Worker(QObject):

    work_finished = QtCore.pyqtSignal(object)

    @QtCore.pyqtSlot()
    def do_work(self):
        data = 'Text'
        while True:
            # Do something with data and pass back to main thread
            data = data + 'text'
            self.work_finished.emit(data)
            time.sleep(10)


class MyWidget(QtGui.QWidget):

    def __init__(self, ...)
        ...
        self.worker = Worker()
        self.thread = QtCore.QThread(self)
        self.worker.work_finished.connect(self.on_finished)
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.do_work)
        self.thread.start()

    @QtCore.pyqtSlot(object)
    def on_finished(self, data):
        self.bilgiler.append(data)
        ...

当主线程退出事件循环时,Qt将自动终止所有子线程。

我选择重写这个答案,因为我未能正确查看问题的背景。 正如其他答案和注释所表明的那样,您的代码缺乏线程安全性。

解决此问题的最佳方法是尝试真正地在“线程中”思考,限制自己只使用位于同一线程中的对象或称为“线程安全”的函数。

插入一些信号和时隙会有所帮助,但也许您想对您的原始问题进行一些反思。 在当前代码中,每按一次按钮,就会启动一个新线程 ,该线程每10秒执行2件事:-从self.text读取一些文本-将其追加到self.bilgiler

这两个操作都是非线程安全的, 必须从拥有这些对象的线程(主线程)中调用。 您希望使工作线程“计划并等待”读取和追加运算,而不是简单地“执行”它们。

我建议使用其他答案(通过使用与Qt的事件循环良好集成的正确QThreads可以自动解决线程停止问题),这将使您使用更简洁的方法,与Qt更加集成。

您可能还想重新考虑问题,因为也许有一种更简单的方法来解决问题,例如:每次单击bilgi_cekbilgi_cek线程,或者不使用Queue对象,以便您的工作人员完全bilgi_cek您的GUI,并且仅进行交互使用线程安全对象。

祝你好运,对不起,如果我引起任何混乱。 我的原始答案仍在这里 我认为将其他答案标记为该问题的有效答案是明智的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM