美文网首页
通过QThread进行进度控制

通过QThread进行进度控制

作者: 雯饰太一 | 来源:发表于2023-07-17 12:40 被阅读0次

说明:

  • 线程类 QSatelliteTrackThread
  • 界面类 QSatelliteTreeWidget
  • 在界面中通过【开始】【暂停】【继续】【停止】来控制线程的运行状态
  • 线程的初始化与销毁是在界面中完成的

线程类

class QSatelliteTrackThread : public QThread
{
    Q_OBJECT
public:

    enum ThreadRunState
    {
        TRS_Begin,
        TRS_Run,
        TRS_Pause,
        TRS_Stop
    };

    QSatelliteTrackThread();
    virtual ~QSatelliteTrackThread();

    void SetThreadRunState(ThreadRunState s);
signals:
void featureCreated(int fId,int t);//传入动目标id,类型 [0:星下点 1:卫星]
    void eventloopBreak();//打破时间循环,以继续或终止
public slots:
    void on_featureCreated(int fId, int t);
    void on_threadTimerWakeUp();        //执行处理逻辑
protected:
    virtual void run();
    bool ContinueCtrl();//进度控制

private:
    QTimer* m_pThreadTimer;
    ThreadRunState m_cState;
};
  • 需要继承Qthread
  • 需要支持外部设置状态,内部进行状态切换
  • 能够在run函数里面进入具体的工作函数

构造函数

QSatelliteTrackThread::QSatelliteTrackThread()
{
    m_cState = TRS_Begin;
    pThreadTimer = nullptr;
}
  • 设置初始状态
  • 设置timer为空

run函数

void QSatelliteTrackThread::run()
{
    m_pThreadTimer = new QTimer;
    m_pThreadTimer->setSingleShot(true);
    connect(m_pThreadTimer, &QTimer::timeout, this, &QSatelliteTrackThread::on_threadTimerWakeUp,Qt::DirectConnection); //保证子程创建工作
    connect(this, &QSatelliteTrackThread::featureCreated, this, &QSatelliteTrackThread::on_featureCreated, Qt::QueuedConnection);//保证主线程创建电磁特效
    m_pThreadTimer->start();
    exec();
    delete m_pThreadTimer;
    disconnect(this, &QSatelliteTrackThread::featureCreated, this, &QSatelliteTrackThread::on_featureCreated);
}
  • 将timer实例化,绑定信号,使其能够在线程中运行 [在线程中运行timer还需要线程启用事件循环]
  • 启动timer,一旦超时,将会激活工作函数on_threadTimerWakeUp
  • 启动事件循环
  • 事件循环结束后,销毁timer并解除自身的绑定

过程控制函数

#include <QEventLoop>
bool QSatelliteTrackThread::ContinueCtrl()
{
    switch (m_cState)
    {
    case QSatelliteTrackThread::TRS_Begin:
        return true;
        break;
    case QSatelliteTrackThread::TRS_Run:
        return true;
        break;
    case QSatelliteTrackThread::TRS_Pause:
    {
        QEventLoop loop;
        connect(this, &QSatelliteTrackThread::eventloopBreak, &loop, &QEventLoop::quit, Qt::QueuedConnection);
        loop.exec();
        return !(m_cState == TRS_Stop);
        break;
    }
    case QSatelliteTrackThread::TRS_Stop:
        return false;
        break;
    default:
        break;
    }
    return false;
}
  • 只有是pause状态的情况下,才需要使用eventloop阻塞线程的运行
  • 相当于只要切换状态的时候,自己发一个信号,就能打破loop,使其继续运行

具体做事情的函数

#include <QTimer>
void QSatelliteTrackThread::on_threadTimerWakeUp()
{
    m_cState = TRS_Run;

    for (qint64 t = m_dtStart; t < m_dtEnd; t += 1000)
    {
        for (int i = 0; i < m_vecSatellite.size(); i++)
        {
            if (!ContinueCtrl()) break;
            //... do something
            //Q_EMIT updateTrack(pSat);
            msleep(10);
        }
        if(!ContinueCtrl()) break;
    }
}
  • 在关键的位置,对状态进行检测,通常这种for循环中才需要

界面类

开始

void QSatelliteTreeWidget::on_pbPlay_clicked(bool checked)
{
    //调整状态
    setPushbuttonEnableState(ui.pbPlay, false);
    setPushbuttonEnableState(ui.pbPause, true);
    setPushbuttonEnableState(ui.pbStop, true);
    ui.pbPause->setText(QString::fromLocal8Bit("暂停"));

    if (m_pSatTrackThread == nullptr)
    {
        m_pSatTrackThread = new QSatelliteTrackThread();
    }
    m_pSatTrackThread->start();
}
  • 设置按钮状态
  • 实例化线程,线程对象是在主线程实例化的,出了他的run函数
  • 其他的被外部调用时,也都是在主线程中的

暂停与继续

void QSatelliteTreeWidget::on_pbPause_clicked(bool checked)
{
    if (!m_pSatTrackThread) return;
    QString text = ui.pbPause->text();
    if (text.compare(QString::fromLocal8Bit("暂停")) == 0)
    {
        m_pSatTrackThread->SetThreadRunState(QSatelliteTrackThread::TRS_Pause);
        ui.pbPause->setText(QString::fromLocal8Bit("继续"));
    }
    else
    {
        m_pSatTrackThread->SetThreadRunState(QSatelliteTrackThread::TRS_Run);
        ui.pbPause->setText(QString::fromLocal8Bit("暂停"));
    }
}

结束

void QSatelliteTreeWidget::on_pbStop_clicked(bool checked /*= false*/)
{
    if (!m_pSatTrackThread) return;
    m_pSatTrackThread->SetThreadRunState(QSatelliteTrackThread::TRS_Stop);

    setPushbuttonEnableState(ui.pbPlay, true);
    setPushbuttonEnableState(ui.pbPause, false);
    setPushbuttonEnableState(ui.pbStop, false);
    ui.pbPause->setText(QString::fromLocal8Bit("暂停"));

    m_pSatTrackThread->quit();
    m_pSatTrackThread->wait();
    delete m_pSatTrackThread;
    m_pSatTrackThread = nullptr;
}
  • 通过quit停止线程
  • 通过wait等待线程finished
  • 只有线程的run函数里面exec后,quit才会生效
  • 销毁线程对象

QRunnable + QObject应该也是可以满足条件的。但是这种方式都是在循环存在的时候成立,在没有循环的情况下,并不能立刻冻结或暂停一个线程。

期望的状态是,通过一个函数能够在任何时间,直接对线程自身的运行施以操控。

相关文章

  • 信息监理师笔记-信息系统工程的进度控制

    三控:进度控制、质量控制、成本控制 一、进度与进度控制 1.进度 计划:指对一个工程项目进行分解,并对分解后的工作...

  • PyQt5多线程QThread实现

    QThread类提供了一种独立于平台的线程管理方法。QThread对象管理程序中的一个控制线程。在run()中开始...

  • 如何正确使用QThread

    1 Qt的线程支持 2 QThread的使用方法 2.1 继承QThread 继承QThread类,并重新实现ru...

  • 软件开发项目进度控制

    要有效地进行进度控制,必须对影响进度的因素进行分析,事先或及时采取必要的措施,尽量缩小计划进度与实际进度的偏差,实...

  • vue 做一个带进度动画的下载按钮

    进度通过VUEX全局控制,就算切换页面你的下载进度也不会丢失并且在其他页面也能通过btn按钮看到下载进度 调用方式...

  • 日常记录(07.13)

    [高项]: 1.“项目进度控制”过程是依据项目的实际进展情况进行控制,使项目能够按时完成。进度控制的一个重要部分是...

  • 通过注解进行权限控制

    1.自定义注解 元注解介绍 @Target @Target说明了Annotation所修饰的对象范围:Annota...

  • 制约工程进度因素

    进度管理就是采用科学的方法、针对项目的具体情况确定进度目标,编制进度计划并进行进度控制,在与质量、成本目标协...

  • JS流程控制

    对js的各个部分进行控制。 顺序流程即为自动进行,而通过if,swith等,可以进行选择控制。通过for whil...

  • 6.2-3 项目进度管理

    七、控制进度 在项目的进行中,要对项目的进度进行监控,看有没有偏差,有偏差要进行纠偏 通常可用以下一些方法缩短活动...

网友评论

      本文标题:通过QThread进行进度控制

      本文链接:https://www.haomeiwen.com/subject/zpfiydtx.html