c++ - Qt 5 : update QProgressBar during QThread work via signal

标签 c++ multithreading qt qt5 qt-signals

我正在尝试在处理一些耗时操作的 QThread 的执行过程中更新 QProgressDialog(由 QMainWindow 类拥有)。线程在操作期间发出一些信号,以通知调用应用程序有关进度。我希望将线程发出的进度信号连接到 QProgressDialog 的 setValue 插槽,以便更新进度条。

没用!不显示进度对话框。如果我在我的 QMainWindow 中添加一个插槽并将其连接到工作进度信号以显示线程通过 qDebug 输出给出的值,我看到信号似乎在线程操作期间堆叠并且仅在线程结束时取消堆叠线程。

我尝试了 DirectConnection 连接选项但没有成功。

这是我的代码: qapp.cpp

#include "qapp.h"
#include <threaded.h>

#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
#include <QProgressDialog>

QApp::QApp(QWidget *parent) :
    QMainWindow(parent)
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    QWidget *window = new QWidget(this);
    window->setLayout(mainLayout);
    setCentralWidget(window);
    QPushButton *button = new QPushButton("Run");
    mainLayout->addWidget(button);
    connect(button, SIGNAL(clicked(bool)), this, SLOT(doSomeWork()));
}

void QApp::doSomeWork()
{
    qDebug() << "do some work";
    Threaded worker;
    worker.doHeavyCaclulations();

    QProgressDialog progressDialog("Copying files...", "Abort Copy", 0, 10000, this);
    progressDialog.setWindowModality(Qt::WindowModal);
    progressDialog.setMinimumDuration(0);
    progressDialog.setValue(0);

    connect(&worker, SIGNAL(progress(int)), &progressDialog, SLOT(setValue(int)));
    connect(&worker, SIGNAL(progress(int)), this, SLOT(displayProgress(int)));

    worker.wait();
    qDebug() << "end of thread";
}

void QApp::displayProgress(int value)
{
    qDebug() << "data received" << value;
}

QApp::~QApp()
{

}

线程.cpp :

#include "threaded.h"
#include <QDebug>

Threaded::Threaded(QObject *parent) : QThread(parent)
{

}

void Threaded::doHeavyCaclulations()
{
    if (!isRunning())
    {
        qDebug() << "start thread"  ;
        start();
    }

}

void Threaded::run()
{
    qDebug() << "running big loop";
    for(double k = 0 ; k < 10000 ; k++)
    {
        qDebug() << k;
        emit progress(k);
    }
}

qapp.h

#ifndef QAPP_H
#define QAPP_H

#include <QMainWindow>

class QApp : public QMainWindow
{
    Q_OBJECT

public:
    explicit QApp(QWidget *parent = 0);
    ~QApp();

private:

private slots:
    void doSomeWork();
    void displayProgress(int value);
};

#endif // QAPP_H

线程.h

#ifndef THREADED_H
#define THREADED_H

#include <QObject>
#include <QThread>

class Threaded : public QThread
{
    Q_OBJECT
public:
    explicit Threaded(QObject *parent = 0);
    void doHeavyCaclulations();
    void run();

private:


signals:
    void progress(int value);

public slots:

};

#endif // THREADED_H

当 k < 100 时,这段代码的输出是:

do some work
start thread
running big loop
0
1
2
3
[...]
97
98
99
end of big loop
end of thread
data received 17
data received 18
data received 19
[...]
data received 99

如果我替换 worker .等待(); 通过

 int k=0;
    while(worker.isRunning())
    {
        qDebug() << "main " << k;
        k++;
    }

我得到交错的线程输出和调用方法的输出。它确认我的线程独立于调用方法。

知道我做错了什么吗?

最佳答案

QThread 的使用绝对错误)。参见 what is the correct way to implement a QThread... (example please...) .你需要学习线程的基础知识。

你的错误:
1. 在局部范围内创建一个静态线程对象;
2. 在主线程中等待它完成;
3.不要启动线程;
4、在主线程中直接调用方法doHeavyCaclulations()
5. 在没有工作事件循环的情况下发出信号以传递...

为了您的目的,您需要:
不要继承QThread。只需创建具有必要功能的简单 Work 类:

class Work: public QObject
{
    Q_OBJECT

public:
    Work(){};
    virtual ~Work(){};

public slots:
    void doHeavyCaclulations() { /* do what you need and emit progress signal */ };

signals: 
    void progress(int);                
}

// Then:
void QApp::doSomeWork()
{
    //...
    QThread* thread = new QThread(parent);
    Work* worker = new Work; // Do not set a parent. The object cannot be moved if it has a parent. 
    worker->moveToThread(thread);

    connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(started()), worker, SLOT(doHeavyCaclulations()));
    connect(worker, SIGNAL(progress(int)), &progressDialog, SLOT(setValue(int)));

    thread->start();        
    //...
}

关于c++ - Qt 5 : update QProgressBar during QThread work via signal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35673201/

相关文章:

c++ - 将一个右值的元组转换为一个左值的元组

c++ - 检测图像的特定矩形部分

java - Java 执行器中无界队列的用例是什么?

java - 读取大文件并通过多线程处理

c++ - 使用 Qt 在 OS X/Mac 上构建 C++ 库

c++ - 来自 C++ 的 QStandardItemModel 在 QtQuick/QML TableView 中不可见

c++ - 将 std::function<void(Derived*)> 转换为 std::function<void(Base*)>

linux - 为什么 Linux 不使用纤程而不是抢占式多任务处理?

android - 如果 Qt3DWindow 嵌入到 QWidget 中,为什么 Qt3D QObjectPicker 无法在 Android 上工作?

c++ - 在 Windows 上从 1_55 更新到 1_62 后,创建一个 boost::asio::ip::udp::socket 在 LIB 中崩溃