[英]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_()
一些东西:
您不应该从主线程之外调用GUI代码。 GUI元素不是线程安全的。 self.kontenjan_ara
更新并读取GUI元素,它不应该成为您thread
的目标。
在几乎所有情况下,都应使用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_cek
时bilgi_cek
线程,或者不使用Queue
对象,以便您的工作人员完全bilgi_cek
您的GUI,并且仅进行交互使用线程安全对象。
祝你好运,对不起,如果我引起任何混乱。 我的原始答案仍在这里 。 我认为将其他答案标记为该问题的有效答案是明智的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.