您的位置:首页 > 编程语言 > Qt开发

Qt线程的简单使用——通过一个实例理解QMutex的使用

2018-02-28 20:52 901 查看
转自:https://www.cnblogs.com/vegetable/p/6653930.html
首先先看一个示例,(示例程序来自,Qt编程快速入门,我做了一些修改)。效果图如下,程序开启了三个绘图线程分别往QImage上绘制三角形、圆和矩形。主程序中开启了一个定时器,会定时将图片清空。除此主程序的paintEvent事件中,将这个图片通过QPainter绘制显示出来。在绘图线程中,当对QImage操作时,就需要进行加锁,以保证同时只有一个线程可以对QImage进行操作。

绘图线程的代码。

1 #ifndef DRAWTHREADING_H
2 #define DRAWTHREADING_H
3 #include <QThread>
4 #include <QWidget>
5 #include <QMutex>
6 class DrawThread:public QThread
7 {
8     Q_OBJECT
9 public:
10     explicit  DrawThread(QWidget *parent = 0);
11     void SetShape(int inputshape);
12 protected:
13     void run();
14 private:
15     int shape;
16 };
17
18 #endif // DRAWTHREADING_H

1 #include "drawthreading.h"
2
3 #include <QTime>
4 #include <QImage>
5 #include <QPainter>
6 #include "mainwindow.h"
7
8 DrawThrea
4000
d::DrawThread(QWidget *parent):QThread(parent)
9 {
10     shape = 0;
11     QTime tm;
12     tm = QTime::currentTime();
13     qsrand(tm.msec());
14 }
15 void DrawThread::SetShape(int inputshape)
16 {
17     shape = inputshape;
18 }
19 void DrawThread::run()
20 {
21     QImage* parentScene = ((MainWindow*)(this->parent()))->m_image;
22
23     while(true)
24     {
25         int x,y;
26         x = qrand()% parentScene->width();
27         y = qrand()% parentScene->height();
28         int r,g,b;
29         r = qrand() % 255;
30         g = qrand() % 255;
31         b = qrand() % 255;
32         ((MainWindow*)(this->parent()))->painterLock.lock();
33         QPainter painter;
34         painter.begin(parentScene);
35         QPen m_pen(QColor(r,g,b));
36         painter.setPen(m_pen);
37         switch(shape)
38         {
39             case 0:
40             painter.drawEllipse(x,y,(qrand() % 10) * 10,(qrand() % 10) * 10);
41             break;
42         case 1:
43             painter.drawRect(qrand() % parentScene ->width(),qrand() % parentScene->height(),(qrand()%10)* 15,(qrand()%10)* 15);
44             break;
45          case 2:
46             painter.drawLine(x-50,y,x+50,y);
47             painter.drawLine(x-50,y,x,y- 50);
48             painter.drawLine(x,y-50,x + 50,y);
49           default:
50             break;
51         }
52         painter.end();
53         ((MainWindow*)(this->parent()))->painterLock.unlock();
54          ((MainWindow*)(this->parent()))->update();
55         this->msleep(100);
56     }
57 }

注意在run()函数中,当对QImage操作时,使用到QMutex对象的lock,当绘图完成之后进行unlock()。主工程代码:
1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3 #include "ui_mainwindow.h"
4 #include <QMainWindow>
5
6 namespace Ui {
7 class MainWindow;
8 }
9 #include"drawthreading.h"
10 #include <QMutex>
11 class MainWindow : public QMainWindow
12 {
13     Q_OBJECT
14
15 public:
16     explicit MainWindow(QWidget *parent = 0);
17     ~MainWindow();
18
19 private:
20    Ui::MainWindow ui;
21 public:
22     DrawThread drawTriangleThread;
23     DrawThread drawEcllipseThread;
24     DrawThread drawRectThread;
25     QImage* m_image;
26     QMutex painterLock;
27     void paintEvent(QPaintEvent*);
28     void timerEvent(QTimerEvent* event);
29 };
30
31 #endif // MAINWINDOW_H

1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3 #include <QThread>
4 #include <QImage>
5 #include <QPainter>
6 MainWindow::MainWindow(QWidget *parent) :
7     QMainWindow(parent)
8 {
9     ui.setupUi(this);
10     this->setAutoFillBackground(true);
11     m_image = new QImage(1024,768,QImage::Format_RGB32);
12     QPainter painter(m_image);
13     QBrush fillBrush(QColor(255,255,255));
14
15    painter.fillRect(0,0,1024,768,fillBrush);
16     this->startTimer(10000);
17
18     drawEcllipseThread.SetShape(0);
19     drawEcllipseThread.setParent(this);
20     drawEcllipseThread.start();
21
22     drawRectThread.SetShape(1);
23     drawRectThread.setParent(this);
24     drawRectThread.start();
25
26     drawTriangleThread.SetShape(2);
27     drawTriangleThread.setParent(this);
28     drawTriangleThread.start();
29 }
30
31 MainWindow::~MainWindow()
32 {
33
34     if (drawEcllipseThread.isRunning())
35     {
36         drawEcllipseThread.quit();
37         drawEcllipseThread.wait();
38     }
39     if (drawRectThread.isRunning())
40     {
41         drawRectThread.quit();
42         drawRectThread.wait();
43     }
44     if (drawTriangleThread.isRunning())
45     {
46         drawTriangleThread.quit();
47         drawTriangleThread.wait();
48     }
49     if (m_image)
50     {
51         delete m_image;
52         m_image = NULL;
53     }
54 }
55
56 void MainWindow::paintEvent(QPaintEvent*)
57 {
58     QPainter painter(this);
59     painter.drawImage(0,0,*m_image);
60
61 }
62 void MainWindow::timerEvent(QTimerEvent* event)
63 {
64     QPainter painter(m_image);
65     QBrush fillBrush(QColor(255,255,255));
66     painter.fillRect(0,0,1024,768,fillBrush);
67 }

我们在Qt帮助中查看QMutex,The QMutex class provides access serialization between threads.The purpose of a QMutex is to protect an object, data structure or section of code so that only one thread can access it at a time (this is similar to the Java synchronized keyword). It is usually best to use a mutex with a QMutexLocker since this makes it easy to ensure that locking and unlocking are performed consistently.翻译过来,大致意思是,QMutex提供提供线程之间访问顺序化。QMutex目的是保护一个对象,数据结构或者一段代码以至于同一时间只能有一个线程访问。(与java中的关键字synchroized的类似)。Qt中的建议是使用QMutexLocker代替QMutex为了更容易的加锁、解锁。使用QMutexLocker对以上的代码进行调整,如下: 
void DrawThread::run()
{
QImage* parentScene = ((MainWindow*)(this->parent()))->m_image;

//注意这里,使用QMutexLocker
QMutexLocker locker(&((MainWindow*)(this->parent()))->painterLock);
while(true)
{
int x,y;
x = qrand()% parentScene->width();
y = qrand()% parentScene->height();
int r,g,b;
r = qrand() % 255;
g = qrand() % 255;
b = qrand() % 255;
//((MainWindow*)(this->parent()))->painterLock.lock();
QPainter painter;
painter.begin(parentScene);
QPen m_pen(QColor(r,g,b));
painter.setPen(m_pen);
switch(shape)
{
case 0:
painter.drawEllipse(x,y,(qrand() % 10) * 10,(qrand() % 10) * 10);
break;
case 1:
painter.drawRect(qrand() % parentScene ->width(),qrand() % parentScene->height(),(qrand()%10)* 15,(qrand()%10)* 15);
break;
case 2:
painter.drawLine(x-50,y,x+50,y);
painter.drawLine(x-50,y,x,y- 50);
painter.drawLine(x,y-50,x + 50,y);
default:
break;
}
painter.end();
//((MainWindow*)(this->parent()))->painterLock.unlock();
((MainWindow*)(this->parent()))->update();
this->msleep(100);
}
}

至此,QMutex的方法已经讲诉完了,总之,QMutex提供提供线程之间访问顺序化。QMutex目的是保护一个对象,数据结构或者一段代码以至于同一时间只能有一个线程访问。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Qt
相关文章推荐