在我的应用程序中有主线程和工作线程(QThread).
从主线程我想调用我的工作线程的方法,让它在线程的上下文中运行.
我已经尝试使用QMetaObject::invokeMethod并给它QueuedConnection选项,但它不起作用.
我也尝试从主线程(连接到工作线程的插槽)发出信号,但也失败了.
这是我尝试的大致的片段:
class Worker : public QThread
{
Q_OBJECT
public:
Worker() { }
void run()
{
qDebug() << "new thread id " << QThread::currentThreadId();
exec();
}
public slots:
void doWork()
{
qDebug() << "executing thread id - " << QThread::currentThreadId();
}
};
Run Code Online (Sandbox Code Playgroud)
使用QMetaObject方式:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "main thread id - " << QThread::currentThreadId();
Worker worker;
worker.start();
QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);
return a.exec();
}
Run Code Online (Sandbox Code Playgroud)
使用信号方式: …
我没有exec()在我的代码中调用,但是timer并且QUdpSocket工作正常.被exec()用于等待的event继续吗?
更新:timer工作正常,因为我没有打电话moveToThread(this)给QThread,这意味着它QThread实际上仍然是其中的一部分main thread.至于QUdpSocket我使用投票functions.所以它不需要合作signals.
提示:如果你需要做init一些东西,那需要event loop你的QThread,你可以delay打电话,moveToThread直到你不再需要它signals,这在程序加载时是实用的.您也不需要在构造函数中调用它run()(例如,您可以在内部调用它),只需将this QThread指针复制到变量并call使用指针在其他地方/其他地方生成.
使用PyQt4 4.8.6,下面的代码会产生错误
QObject :: startTimer:QTimer只能用于以QThread启动的线程
当a用作QApplication的变量时,如果cpp(或大多数其他)用于变量,它不会产生错误.这是PyQt4中的错误还是我缺少的东西?
#! /usr/bin/env python
# This is only needed for Python v2 but is harmless for Python v3.
import sip
sip.setapi('QVariant', 2)
from PyQt4 import QtGui
#def main():
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
use_a = False
print "Don't use a"
else:
use_a = True
print "Use a"
if use_a:
a = QtGui.QApplication(sys.argv)
else:
cpp = QtGui.QApplication(sys.argv)
model = QtGui.QStandardItemModel(4,2)
tableView = QtGui.QTableView()
tableView.setModel(model)
tableView.show()
if use_a:
sys.exit(a.exec_())
else:
sys.exit(cpp.exec_())
#if …Run Code Online (Sandbox Code Playgroud) 我最近开始学习QThreads,我有一个程序在一个单独的线程中运行4个小时的循环(这样我可以继续使用GUI).我所追求的是,当用户点击暂停qpushbutton时暂停/暂停线程的东西,当用户点击恢复qpushbutton时,程序应该恢复.我怎么能实现这个目标?
我正在考虑从我的主班发送信号; 但是,我不确定如何在线程中处理它们.是否可以处理线程中主类发送的信号?目前,我有线程向主类发出信号,并且工作正常,但我不知道如何从主类发送线程,并在线程中接收它们.
我有一个内部带有while循环的Python代码,但是我不知道如何使其与我的PyQt GUI一起工作-我只能运行Qt窗口或该循环(但窗口不会显示)。有什么解决办法吗?我读了一些QThreads或QTimers,但我不知道如何使用它。
在下面的示例中(在Qt GUI应用程序中)启动了一个新线程(带有一个事件循环,我希望在其中完成一些工作):
void doWork()
{
QThread* workerThread = new QThread();
Worker* worker = new Worker();
worker->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), worker, SLOT(startWork()));
connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();
}
Run Code Online (Sandbox Code Playgroud)
startWork() 可以是一个长时间运行的操作,在此期间可以关闭应用程序.
我希望只要在应用程序startWork()上执行应用程序就不会关闭workerThread.但是,当我关闭最后一个应用程序窗口时,它workerThread会立即消失(在长时间运行期间)并且应用程序关闭没有问题.
问题出现了:
workerThread擦拭?
wait()QThread(最终)?
wait()进入一个插槽,aboutToQuit()并且在长时间运行操作完成后应用程序没有关闭(如上所述设置).仅quit(); wait();(在提到的插槽内)允许应用程序关闭.为什么?我认为确定QThread当前运行函数的ID 是QThread.currentThreadId().但是我发现这没有给出预期的结果(在PyQt5中使用python 3;但是我没有理由相信它与pyqt4/py 2不同,因此通用标签).线程ID以我无法解释的方式变化,表明我实际上无法使用它,QThread实例id可预测地变化,表明我应该使用它来识别当前正在运行的线程.为了测试,我创建了这个:
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import pyqtSignal
import time
import sys
def logthread(caller):
print('%-25s: %s, %s' % (caller, QtCore.QThread.currentThread(), QtCore.QThread.currentThreadId()))
class Worker(QtCore.QObject):
done = pyqtSignal()
def __init__(self, parent=None):
logthread('worker.__init__')
super().__init__(parent)
def run(self, m=10):
logthread('worker.run')
for x in range(m):
y = x + 2
time.sleep(0.001)
logthread('worker.run finished')
self.done.emit()
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
logthread('mainwin.__init__')
super().__init__(parent)
self.worker = Worker()
self.workerThread = None
self.btn = QtWidgets.QPushButton('Start worker in thread')
self.btn2 = QtWidgets.QPushButton('Run worker …Run Code Online (Sandbox Code Playgroud) 运行bat文件的程序,其中包含使用Qthread运行可执行文件(longTask)的指令,但是当我使用Pyinstaller通过以下命令创建可执行文件时,该程序无法按预期工作。我给“ --windowed”提供了标准I / O的控制台窗口
pyinstaller --onefile --windowed main.py
但是有趣的是,当我删除--windowed参数时,它可以按预期工作
pyinstaller --onefile main.py
Run Code Online (Sandbox Code Playgroud)
这是代码:
from PyQt4.Qt import *
import subprocess
def callSubprocess():
page = QWizardPage()
page.setTitle("Run myLongTask")
runButton = QPushButton("Run")
progressBar = QProgressBar()
procLabel = QLabel()
procLabel1 = QLabel()
progressBar.setRange(0, 1)
layout = QGridLayout()
layout.addWidget(runButton, 0, 0)
layout.addWidget(progressBar, 0, 1)
layout.addWidget(procLabel)
layout.addWidget(procLabel1)
# Calls thread class
myLongTask = TaskThread()
runButton.clicked.connect(lambda: OnStart(myLongTask, progressBar, procLabel1))
myLongTask.taskFinished.connect(lambda: onFinished(progressBar, procLabel))
page.setLayout(layout)
return page
def OnStart(myLongTask, progressBar, procLabel1):
progressBar.setRange(0, 0)
myLongTask.start()
# I am waiting until …Run Code Online (Sandbox Code Playgroud) 这个问题似乎已经多次以多种不同形式提出,但我没有找到一个与我的代码解决方案相关的问题.
当我运行它显示的程序时
QObject :: installEventFilter:无法过滤不同线程中对象的事件.
尽管如此,代码最初工作,但一段时间后炸弹和python发出错误说它停止工作.
我的代码如下:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from xml.etree import ElementTree as ET
import os , time
class LayoutCreator(QDialog):
def __init__(self , parent=None):
super(LayoutCreator, self).__init__(parent)
self.Cameras_Update()
def Cameras_Update( self ): # Get all shots with camera plots and add them to the cameras_tree
busyBar = sqrl_QtTools.BusyBar( text = "Gathering Camera Data" ) # Looping progress bar
busyBar.start()
# loop through folder structure storing data
busyBar.Kill() # Close looping progress bar
class BusyBar(QThread): …Run Code Online (Sandbox Code Playgroud) 我正在尝试暂停 QThread 并恢复它。
所以,我在 QThread 中有一个 RFID 读取循环,我想在读取器获得 RFID 代码时暂停无限循环。之后,进行数据库检查。在检查结束时,我想恢复 RFID 读取循环以获取其他代码。
MVCE:
def main():
global Thread
app = QtGui.QApplication(sys.argv)
main = Main()
Thread = RFID_Thread()
Thread.rfid_event.connect(Main().on_event)
Thread.start()
sys.exit(app.exec_())
class Main(object):
def __init__(self):
self.accueil = MainWindow(self)
self.access = AccessWindow()
self.accueil.show()
def on_event(self, data):
# I WANT TO PAUSE THE QTHREAD HERE
###################################
# CHECKING DB & SHOWING UI #
###################################
# AND RESUME IT HERE
class RFID_Thread(QtCore.QThread):
rfid_event = pyqtSignal(str, name='rfid_event')
def run(self):
while 1:
ser = serial.Serial(port=Serial_Port, baudrate=Serial_Baudrate)
a …Run Code Online (Sandbox Code Playgroud)