我的代码有线程,但是当我关闭gui时,它仍然可以在后台运行。我怎么能阻止线程?有什么东西stop(),close()? 我不使用信号,插槽?我必须用这个吗?
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_()
答案 0 :(得分:3)
一些事情:
您不应该从主线程外部调用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将自动终止所有子线程。
答案 1 :(得分:2)
我选择重写这个答案,因为我未能正确看待问题的背景。正如其他答案和评论所说,您的代码缺乏线程安全性。
解决这个问题的最好方法是尝试在线程中真正思考",限制自己只使用生活在同一个线程中的对象,或称为"线程安全&## 34。
投掷一些信号和插槽会有所帮助,但也许你想回想一下原来的问题。在您当前的代码中,每次按下按钮时,启动的新主题,即每10秒执行两项操作:
- 阅读self.text
中的一些文字
- 将其附加到self.bilgiler
这两个操作都是非线程安全的,并且必须从拥有这些对象的线程(主线程)中调用。你想让工作线程" schedule& amp;等待"阅读&附加oeprations,而不仅仅是"执行"它们。
我建议使用另一个答案(通过使用与Qt事件循环良好集成的正确QThreads自动修复线程停止问题),这将使您使用更清晰的方法,与Qt集成更多。
您可能还想重新考虑您的问题,因为可能有一种更简单的方法来处理您的问题,例如:每次点击bilgi_cek
时都不会产生线程,或者使用Queue
对象以便您的问题worker完全不知道你的GUI,只能使用线程安全对象与它进行交互。