我有这段代码(如果你有pyqt5,你应该能够自己运行它):
import sys
import time
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
class Worker(QObject):
def __init__(self):
super().__init__()
self.thread = None
class Tab(QObject):
def __init__(self, _main):
super().__init__()
self._main = _main
class WorkerOne(Worker):
finished = pyqtSignal()
def __init__(self):
super().__init__()
@pyqtSlot(str)
def print_name(self, name):
for _ in range(100):
print("Hello there, {0}!".format(name))
time.sleep(1)
self.finished.emit()
self.thread.quit()
class SomeTabController(Tab):
def __init__(self, _main):
super().__init__(_main)
self.threads = {}
self._main.button_start_thread.clicked.connect(self.start_thread)
# Workers
self.worker1 = WorkerOne()
#self.worker2 = WorkerTwo()
#self.worker3 = WorkerThree()
#self.worker4 …Run Code Online (Sandbox Code Playgroud) 我有一个 GUI,我需要使用 Qtimer 不断更新,因为我使用工作 Qthread,这是我的代码:
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget
from PyQt5.QtCore import QThread, QTimer
import sys
import threading
class WorkerThread(QThread):
def run(self):
print("thread started from :" + str(threading.get_ident()))
timer = QTimer(self)
timer.timeout.connect(self.work)
timer.start(5000)
self.exec_()
def work(self):
print("working from :" + str(threading.get_ident()))
QThread.sleep(5)
class MyGui(QWidget):
worker = WorkerThread()
def __init__(self):
super().__init__()
self.initUi()
print("Starting worker from :" + str(threading.get_ident()))
self.worker.start()
def initUi(self):
self.setGeometry(500, 500, 300, 300)
self.pb = QPushButton("Button", self)
self.pb.move(50, 50)
self.show()
app = QApplication(sys.argv)
gui = MyGui()
app.exec_() …Run Code Online (Sandbox Code Playgroud) 我正在使用 PyQt5 创建一个应用程序,它有一个非常简单的用户界面。有一个下拉列表,可以从中选择一个值,然后有一个按钮,可以单击该按钮,然后将根据下拉列表中的当前值执行操作。
目前,如果我运行下面的代码,我可以从下拉列表中获取一个值,并将在myaction.myaction(customer_name)运行之前将其发送到工作线程。代码也运行良好,但是当工作线程中的函数运行时,GUI 没有按照我希望的方式工作。当我单击开始按钮时,它应该向 GUI 发出一个信号以禁用该按钮,更改其标签和颜色,但这种情况永远不会发生。当函数完成后,它应该变回原来的形式。
问题是我如何处理信号,还是我的类中有多余的函数?每次单击按钮时将该下拉列表值发送到工作线程的正确方法是什么,以便我可以简单地将其用作那里的变量?
我在网上找到的每一个可能的解决方案都让我很兴奋,但它们都还没有为我工作,或者其中一些对我来说太混乱而无法理解。
这是我已经浏览过的一些答案
#!/usr/bin/env python3
import sys
#import myaction
import time
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton, QComboBox, QLabel
from PyQt5 import QtCore
class ConfWorker(QtCore.QThread):
updated_button = QtCore.pyqtSignal(list)
updated_label = QtCore.pyqtSignal(str)
updated_error = QtCore.pyqtSignal(str)
request_signal = QtCore.pyqtSignal()
customer = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(ConfWorker, self).__init__(parent)
self.customer.connect(self.getcustomer)
def run(self):
self.request_signal.emit()
def getcustomer(self, text):
self.configure(text)
def configure(self, customer_name):
self.updated_button.emit(["In progress...", False]) …Run Code Online (Sandbox Code Playgroud) 这有什么问题吗?它给了我奇怪的编译错误:
候选函数不可行:第二个参数没有从“void (QThread::*)(QThread::QPrivateSignal)”到“const char *”的已知转换
QTimer timer;
timer.setInterval(3000);
connect(&timer, &QTimer::timeout, this, &ThisClass::runConnectionCheck);
QThread connectionThread;
timer.moveToThread(&connectionThread);
connect(&connectionThread, &QThread::started, &timer, &QTimer::start);
connectionThread.start();
Run Code Online (Sandbox Code Playgroud) QThread文档建议了两种使代码在单独的线程中运行的方法。如果我子类化 QThread 并重新实现 run(),那么我得到
QBasicTimer::start: Timers cannot be started from another thread
Run Code Online (Sandbox Code Playgroud)
-
#include <QWidget>
#include <QThread>
#include <QBasicTimer>
#include <QDebug>
#include <QEvent>
#include <QCoreApplication>
class Worker : public QThread
{
Q_OBJECT
int id;
bool m_abort = false;
bool compute = false;
public:
Worker() {}
protected:
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == id) {
compute = true;
} else {
QObject::timerEvent(event);
}
}
public slots:
void abort() {m_abort = true;}
void run() {
qDebug() << QThread::currentThreadId();
QBasicTimer …Run Code Online (Sandbox Code Playgroud) 对于一个简单的聊天程序,我使用通过boost :: python包装的ac lib.
使用PyQT编写一个简单的GUI.通过对所述lib的阻塞调用来完成接收消息.为了使GUI独立刷新,通信部分处于QThread中.
虽然我认为GUI和通信是独立的,但GUI非常无响应,似乎只在消息进入时才更新.
#!/usr/bin/env python
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import pynetcom2
import time
class NetCom(QThread):
def __init__(self):
QThread.__init__(self)
self.client = pynetcom2.Client()
self.client.init('127.0.0.1', 4028)
self.client.provide('myChat', 1)
self.client.subscribe('myChat', 100)
def run(self):
while (1):
print "Waiting for message..."
text = self.client.recvStr('myChat', True)
return
class Netchat(QMainWindow):
def __init__(self, argv):
if (len(argv) != 2):
print "Usage: %s <nickname>" %(argv[0])
sys.exit(1)
self.nickname = argv[1]
print "Logging in with nickname '%s'" %(self.nickname)
super(Netchat, self).__init__()
self.setupUI()
rect = QApplication.desktop().availableGeometry() …Run Code Online (Sandbox Code Playgroud) 所以我有一个有2个插槽的工作类:StartWork()和StopWork(),StartWork()运行一个无限循环(它只是读取和读取摄像头输入不停),StopWork()方法只是设置一个bool变量为false(因此StartWork()内的循环停止).
根据QThread文档,现在使用它们的最佳方法不是通过子类化,而是通过将工作者移动到线程中,这就是我所做的.问题是,来自线程的started()信号被调用,但是完成的()信号永远不会被调用.
工人类槽:
void StartWork(){running = true; 而(跑步){做工; }}
void StopWork(){running = false; }
QThread初始化和信号/插槽连接:
thread = new QThread();
worker = new Worker();
worker.moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), worker, SLOT(StartWork()));
QObject::connect(thread, SIGNAL(finished()), worker, SLOT(StopWork()));
Run Code Online (Sandbox Code Playgroud)
在我的QPushButton上,我这样做:
if(pushStartStop->text().toLower() == "start")
{
pushStartStop->setText("Stop");
thread->start();
}
else
{
pushStartStop->setText("Start");
thread->quit();
}
Run Code Online (Sandbox Code Playgroud)
thread-> start()工作正常,StartWork()被调用,一切都很漂亮(GUI运行没有块等).
但是thread-> quit()没有做任何事情,它被调用(因为按钮改变文本),但就是这样.如果我只是调用worker-> StopWork()它可以工作,但我不能再启动它.
我尝试过thread-> exit(); 但结果是一样的.我也知道子类分类工作,但它看起来更丑陋,根据最近的Qt文档,子分类不再是最佳的.
提前致谢.
我创建了自己的TestService,它运行在一个单独的QThread,但MainLoop终止时,QThread::finished信号不会被发出.我看到了一个类似的问题,但问题略有不同,因为OP超载QThread而我只是将我的类移到线程上.
请注意,我不超载的QThread课,我只重载QObject基于这个例子:http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation /
这是我的TestService班级:
#include <QObject>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <iostream>
using namespace std;
class TestService: public QObject
{
Q_OBJECT;
private:
volatile int _count;
QWaitCondition _monitor;
QMutex _mutex;
QThread* _thread;
public:
TestService(int numSeconds)
{
_count = numSeconds;
_thread = NULL;
cout << "TestService()" << endl;
}
virtual ~TestService()
{
cout << "~TestService()" << endl;
}
void …Run Code Online (Sandbox Code Playgroud) 我希望从lambda异步执行代码,同时保持eventloop的运行,我想:这可以工作...
auto thread = QSharedPointer<QThread>(new QThread);
QEventLoop l;
connect( thread.data(), &QThread::finished, &l, &QEventLoop::quit );
connect( thread.data(), &QThread::started, [=]() {
for(int i=0; i<100; ++i ) {
qDebug() << "waiting... " << i;
}
QThread::currentThread()->sleep(10);
} );
thread->start();
l.exec();
auto const fin = thread->wait();
qWarning() << fin;
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,但是:当线程完成其lambda函数时,我没有得到任何帮助。它似乎finished没有发出,并且wait(即使没有额外的事件循环)也将永远阻塞。
如何使事件循环退出或等待返回?还是有更好的方法让lambda在另一个线程中运行,并通过非阻塞事件循环等待它?
谢谢
我想知道如何正确停止QThread.我在一个线程中有一个无限循环,我想在我做一个特定的动作时停止它:
我试过了 :
if (thread->isRunning()){
worker->stop();
thread->terminate();
}
Run Code Online (Sandbox Code Playgroud)
stop()方法将值设置为false以退出无限循环.
此外,我真的不明白quit(),terminate()或wait()之间的区别.有人可以解释一下吗?
谢谢.