QT 多线程编程系列7:QMutex主线程使用QTimer直接调用子线程函数

1.工程文件

#-------------------------------------------------
#
# Project created by QtCreator 2023-04-16T14:09:24
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = DiceThreadQMutex
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        main.cpp \
        dialog.cpp \
        qdicethread.cpp

HEADERS += \
        dialog.h \
        qdicethread.h

FORMS += \
        dialog.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    res.qrc

2.线程类

#ifndef QDICETHREAD_H
#define QDICETHREAD_H

#include    <QThread>
#include    <QMutex>

class QDiceThread : public QThread
{
    Q_OBJECT

private:
    QMutex m_mutex;

    int m_seq = 0;
    int m_diceValue;
    bool m_paused = true;
    bool m_stop =  false;

protected:
    void run() Q_DECL_OVERRIDE;

public:
    QDiceThread();

    void diceBegin();
    void diceEnd();
    void stopThread();

    bool readValue(int *seq, int *diceValue);
};

#endif // QDICETHREAD_H
#include "qdicethread.h"
#include <QTime>

QDiceThread::QDiceThread()
{

}

void QDiceThread::diceBegin()
{
    m_paused=false;
}

void QDiceThread::diceEnd()
{
    m_paused=true;
}

void QDiceThread::stopThread()
{
    m_stop=true;
}

bool QDiceThread::readValue(int *seq, int *diceValue)
{
    if(m_mutex.tryLock())
    {
        *seq = m_seq;
        *diceValue = m_diceValue;
        m_mutex.unlock();

        return true;
    } else {
        return false;
    }
}

void QDiceThread::run()
{
    m_stop = false;
    m_seq = 0;
//    qsrand(QTime::currentTime().msec());

    while(!m_stop)
    {
        if(!m_paused)
        {
            m_mutex.lock();
            m_diceValue = qrand();
            m_diceValue = (m_diceValue % 6 ) + 1;
            m_seq++;
            m_mutex.unlock();
        }
        msleep(500);
    }
}

这里定义了QMutex 的成员变量m_mutex

与成员函数readValue;

3.显示对话框类

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

#include    <QTimer>
#include    "qdicethread.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

private:
    int mSeq,mDiceValue;

    QDiceThread   threadA;
    QTimer  mTimer;//定时器

protected:
    void    closeEvent(QCloseEvent *event);

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();

private slots:
    void on_btnStartThread_clicked();

    void on_btnDiceBegin_clicked();

    void on_btnDiceEnd_clicked();

    void on_btnStopThread_clicked();

    void on_btnClear_clicked();

    void    onthreadA_started();
    void    onthreadA_finished();

    void    onTimeOut(); //定期器处理槽函数

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H
#pragma execution_character_set("utf-8")

#include "dialog.h"
#include "ui_dialog.h"

void Dialog::closeEvent(QCloseEvent *event)
{
    if (threadA.isRunning())
    {
        threadA.stopThread();
        threadA.wait();
    }
    event->accept();
}

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    connect(&threadA,SIGNAL(started()),this,SLOT(onthreadA_started()));
    connect(&threadA,SIGNAL(finished()),this,SLOT(onthreadA_finished()));

    connect(&mTimer,SIGNAL(timeout()),this,SLOT(onTimeOut()));
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::onthreadA_started()
{
    ui->LabA->setText("Thread状态:thread started");
}

void Dialog::onthreadA_finished()
{
    ui->LabA->setText("Thread状态:thread finished");
}

void Dialog::onTimeOut()
{ //定时器到时处理槽函数
    int tmpSeq=0,tmpValue=0;
    bool  valid=threadA.readValue(&tmpSeq,&tmpValue); //读取数值
    if (valid && (tmpSeq!=mSeq)) //有效,并且是新数据
    {
        mSeq=tmpSeq;
        mDiceValue=tmpValue;
        QString  str=QString::asprintf("第 %d 次掷骰子,点数为:%d",mSeq,mDiceValue);
        ui->plainTextEdit->appendPlainText(str);
        QPixmap pic;
        QString filename=QString::asprintf(":/dice/images/d%d.jpg",mDiceValue);
        pic.load(filename);
        ui->LabPic->setPixmap(pic);
    }
}

void Dialog::on_btnStartThread_clicked()
{
    mSeq=0;
    threadA.start();

    ui->btnStartThread->setEnabled(false);
    ui->btnStopThread->setEnabled(true);

    ui->btnDiceBegin->setEnabled(true);
    ui->btnDiceEnd->setEnabled(false);
}

void Dialog::on_btnDiceBegin_clicked()
{
    threadA.diceBegin();
    mTimer.start(100); //定时器100读取一次数据
    ui->btnDiceBegin->setEnabled(false);
    ui->btnDiceEnd->setEnabled(true);
}

void Dialog::on_btnDiceEnd_clicked()
{
    threadA.diceEnd();
    mTimer.stop();

    ui->btnDiceBegin->setEnabled(true);
    ui->btnDiceEnd->setEnabled(false);
}

void Dialog::on_btnStopThread_clicked()
{
    threadA.stopThread();//结束线程的run()函数执行
    threadA.wait();//

    ui->btnStartThread->setEnabled(true);
    ui->btnStopThread->setEnabled(false);

    ui->btnDiceBegin->setEnabled(false);
    ui->btnDiceEnd->setEnabled(false);
}

void Dialog::on_btnClear_clicked()
{
    ui->plainTextEdit->clear();
}

4. 主函数文件

#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值