需求:
有3条线程,可以分别输出A、B、C,有序的控制输出顺序为ABCABCABCABCABCABC共6组,放到UI的标签中显示,每条线程只能启动一次;
分析:
Qt里面,创建多线程的方式,可以是重写run函数,也可以使用moveToThread的方式,实现顺序控制之后,还得想办法从子线程里面,将结果放到主线程的标签中显示,就得考虑使用信号槽来通信了,因为Qt里面是不能使用子线程来直接创建UI的。
好了,分析完成,上代码:
核心代码:
方式1:重写run函数的方式
头文件:
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(int val,QString str);
signals:
void strSignal(QString);
protected:
void run();
private:
int m_val;
QString m_str;
};
#endif // MYTHREAD_H
源文件:
#include "mythread.h"
#include <mutex>
#include <condition_variable>
#include <QDebug>
using namespace std;
mutex g_mutex;
condition_variable g_conv;
int g_cnt = 0;
MyThread::MyThread(int val,QString str)
{
m_val = val;
m_str = str;
}
void MyThread::run()
{
for(int i=0;i<6;++i){
unique_lock<mutex> ul(g_mutex);
g_conv.wait(ul,[=]{return g_cnt % 3 == m_val;});
qDebug()<<m_str;
emit strSignal(m_str);
++g_cnt;
g_conv.notify_all();
}
}
使用的操作:
主界面头文件:
#ifndef TESTMAINWINDOW_H
#define TESTMAINWINDOW_H
#include <QMainWindow>
#include "mythread.h"
namespace Ui {
class TestMainWindow;
}
class TestMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit TestMainWindow(QWidget *parent = 0);
~TestMainWindow();
private slots:
void showStr(QString str);
void on_pushButton_clicked();
private:
Ui::TestMainWindow *ui;
MyThread *m_a;
MyThread *m_b;
MyThread *m_c;
};
#endif // TESTMAINWINDOW_H
主界面源文件:
#include "testmainwindow.h"
#include "ui_testmainwindow.h"
TestMainWindow::TestMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TestMainWindow)
{
ui->setupUi(this);
m_a = new MyThread(0,"A");
m_b = new MyThread(1,"B");
m_c = new MyThread(2,"C");
connect(m_a,SIGNAL(strSignal(QString)),this,SLOT(showStr(QString)));
connect(m_b,SIGNAL(strSignal(QString)),this,SLOT(showStr(QString)));
connect(m_c,SIGNAL(strSignal(QString)),this,SLOT(showStr(QString)));
}
TestMainWindow::~TestMainWindow()
{
delete ui;
m_a->deleteLater();
m_b->deleteLater();
m_c->deleteLater();
}
void TestMainWindow::showStr(QString str)
{
QString text = ui->label->text();
ui->label->setText(text+str);
}
void TestMainWindow::on_pushButton_clicked()
{
m_a->start();
m_b->start();
m_c->start();
}
运行效果展示:
第二种方式:moveToThread
头文件:
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <mutex>
#include <condition_variable>
using namespace std;
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(int val,QString str,QObject *parent = nullptr);
signals:
void abcSignal(QString);
public slots:
void showABC();
private:
int m_val;
QString m_str;
static int m_cnt;
static mutex m_mutex;
static condition_variable m_conv;
};
#endif // MYTHREAD_H
源文件:
#include "mythread.h"
#include <QDebug>
#include <QThread>
int MyThread::m_cnt = 0;
mutex MyThread::m_mutex;
condition_variable MyThread::m_conv;
MyThread::MyThread(int val,QString str,QObject *parent) : QObject(parent)
{
m_val = val;
m_str = str;
}
void MyThread::showABC()
{
qDebug()<<QThread::currentThread()<<m_val<<m_str;
for(int i=0;i<6;++i){
unique_lock<mutex> ul(m_mutex);
m_conv.wait(ul,[=]{return m_cnt % 3 == m_val;});
emit abcSignal(m_str);
m_cnt++;
m_conv.notify_all();
}
}
使用的操作:
头文件:
#ifndef MOVETTMAINWINDOW_H
#define MOVETTMAINWINDOW_H
#include <QMainWindow>
#include "mythread.h"
#include <QThread>
namespace Ui {
class MoveTTMainWindow;
}
class MoveTTMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MoveTTMainWindow(QWidget *parent = 0);
~MoveTTMainWindow();
private slots:
void on_pushButton_clicked();
void showABCToLabel(QString str);
private:
Ui::MoveTTMainWindow *ui;
MyThread *m_a;
QThread *m_aThread;
MyThread *m_b;
QThread *m_bThread;
MyThread *m_c;
QThread *m_cThread;
};
#endif // MOVETTMAINWINDOW_H
源文件:
#include "movettmainwindow.h"
#include "ui_movettmainwindow.h"
MoveTTMainWindow::MoveTTMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MoveTTMainWindow)
{
ui->setupUi(this);
m_a = new MyThread(0,"A");
m_aThread = new QThread;
m_b = new MyThread(1,"B");
m_bThread = new QThread;
m_c = new MyThread(2,"C");
m_cThread = new QThread;
m_a->moveToThread(m_aThread);
m_b->moveToThread(m_bThread);
m_c->moveToThread(m_cThread);
connect(m_aThread,SIGNAL(started()),m_a,SLOT(showABC()));
connect(m_bThread,SIGNAL(started()),m_b,SLOT(showABC()));
connect(m_cThread,SIGNAL(started()),m_c,SLOT(showABC()));
connect(m_a,SIGNAL(abcSignal(QString)),this,SLOT(showABCToLabel(QString)));
connect(m_b,SIGNAL(abcSignal(QString)),this,SLOT(showABCToLabel(QString)));
connect(m_c,SIGNAL(abcSignal(QString)),this,SLOT(showABCToLabel(QString)));
}
MoveTTMainWindow::~MoveTTMainWindow()
{
delete ui;
delete m_a;
delete m_b;
delete m_c;
m_aThread->deleteLater();
m_bThread->deleteLater();
m_cThread->deleteLater();
}
void MoveTTMainWindow::on_pushButton_clicked()
{
m_aThread->start();
m_bThread->start();
m_cThread->start();
}
void MoveTTMainWindow::showABCToLabel(QString str)
{
ui->label->setText(ui->label->text()+str);
}