我当前正在尝试单击按钮时进行API调用,而在调用过程中不暂停我的GUI。我使用线程将Qlable的文本设置为API调用的响应。这行得通,但是由于我要从单独的线程访问GUI元素,因此这是不安全的。
当前,我正在尝试使用QThreads进行API调用,然后发出对GUI线程的响应,但是,当我创建Qthread对象时,我的程序以退出代码3结尾。清晰。
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("TestWindow")
self.setFixedSize(300,75)
self.main_layout = QtWidgets.QGridLayout()
self.setLayout(self.main_layout)
self.txt_0 = QtWidgets.QLabel()
self.btn_0 = QtWidgets.QPushButton('Press Me')
self.btn_0.clicked.connect(self.btn_0_clicked)
self.main_layout.addWidget(self.txt_0, 0, 0)
self.main_layout.addWidget(self.btn_0, 1, 0)
self.show()
def btn_0_clicked(self):
temp_thread = StringThread("name")
temp_thread.start()
class StringThread(QtCore.QThread):
str_signal = QtCore.pyqtSignal(str)
_name = ''
def __init__(self, name):
QtCore.QThread.__init__(self)
self._name = name
print("Thread Created")
def run(self):
self.str_signal.emit('Emitted message from StringThread. Name = ' + self._name)
print("Done run")
我的目的是将Qlable的文本设置为StringThread类中pyqtSignal发出的消息,但是,一旦我单击按钮,程序就会以退出代码3结束。
编辑:
我对btn_0_clicked方法进行了以下更改
def btn_0_clicked(self):
self.temp_thread = StringThread("hello")
self.temp_thread.str_signal.connect(self.txt_0.setText)
self.temp_thread.start()
现在正在工作。
答案 0 :(得分:0)
You should probably read up on the Qt C++ documentation to better understand what is happening:
In general you have two problems (one of which is worth listing twice, to examine it from different angles):
QThread
is owned/associated by/with the thread that created it for the purpose of emitting events. So all code trying to emit events is actually trying to access the event loop of your main thread (UI). Read up on QObject
's thread()
and moveToThread()
methods to understand this more fully.run()
method of QThread
which is what is invoked on the actual thread represented by QThread
(i.e. the code that winds up getting called eventually once you call start()
on the thread). So you are effectively trying to access the main event loop in an unsafe manner from a different thread.run()
method of QThread
. The default implementation of QThread
sets up a QEventLoop
, runs it and that is what gives QObject
's associated/owned with/by that thread the ability to use signal/slots freely. You probably did not intend to lose that default implementation.Basically what you want to do instead is this:
QThread
. Instead write a custom QObject
worker subclass with appropriate eventsQThread
with an eventloop (the default IIRC, but check the docs)QThread
with moveToThread()
.QEventLoop
.QThread
and clean up associated resources. Typically you would fire a custom event wired up to the destroyLater()
slot to get rid of your worker object. You may want to cache/reuse the QThread
for subsequent button clicks or you may want to tear it down as well once your worker object has been cleaned up.