Qt多线程绘图并实时刷新画⾯的⽅法
本⼈初学Qt,学习绘画部分,决定⽤多线程绘图
多线程绘图⽅法:
在主线程类⾥⾯设置⼀个QPixmap指针,作为主要画布。
pixmap=new QPixmap(this->size());
pixmap->fill(Qt::white);
主类覆写paintEvent函数
void MainWindow::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.drawPixmap(0,0,*pixmap,0,0,0,0);
}
线程类同样设置QPixmap指针,并且在构造函数接收主线程画布指针
myThread::myThread(QPixmap *pixmap):
pixmap(pixmap)
{
}
线程类覆写run()⽅法,实时绘图
void myThread::run(){
int i=50;
while(i<100){
i++;
QPainter painter(pixmap);
painter.drawLine(100,i,200,i);
QThread::msleep(SLEEP_TIME_MS);
}
}
主线程启动⼦线程
myThread *m0=new myThread(pixmap);
QThreadPool::globalInstance()->start(m0);
除此之外,还可以通过Qt信号槽的变量传递机制,⼦线程将绘制好的图像传递给主线程,再由主线程对图像进⾏绘制。但是如果是需要多个⼦线程⼀起绘制⼀幅图像,显然就不能⽤这种⽅法了。
编译运⾏,应该是⼀条横线垂直向下移动,逐渐绘制形成⼀个矩形的动画,但是结果是⼀条静⽌的横线
原因是主界⾯不能够实时刷新图像。⽤于绘制图像的repaintEvent()函数是在程序初始化时⾃动调⽤⼀次,因此主界⾯只显⽰⼀条静⽌的横线。解决办法是通过repain()或者update()函数让界⾯进⾏实时刷新
实时刷新画⾯:
⽅法⼀:使⽤信号槽机制在⼦线程调⽤主界⾯的repaint函数
⼦线程类增加信号rep()
signals:
void rep();
⼦线程每次绘图后发射信号
void myThread::run(){
int i=50;
while(i<100){
i++;
QPainter painter(pixmap);
painter.drawLine(100,i,200,i);
QThread::msleep(SLEEP_TIME_MS);
emit rep();
}
}
主线程connect函数
connect(m0,SIGNAL(rep()),this,SLOT(repaint()));
除此之外,也可以在⼦线程中使⽤QMetaObject::invokeMethod()⽅法直接调⽤主界⾯的repaint()函数达到相同的⽬的⽅法⼆:利⽤定时器实时刷新界⾯
主线程定义槽函数
protected slots:
void onTimeOut(){
repaint();
}
主线程定义定时器,并且关联槽函数
QTimer *qt0=new QTimer();
qt0->setInterval(REPAINT_TIME);
qt0->start();
connect(qt0,SIGNAL(timeout()),this,SLOT(onTimeOut()));
这样就可以每隔⼀段时间⾃动刷新界⾯
编译运⾏,成功得到了实时刷新的动态画⾯
源代码:
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
();
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);    ~MainWindow();
void paintEvent(QPaintEvent *); private:
Ui::MainWindow *ui;
QPixmap *pixmap;
protected slots:
void onTimeOut(){
repaint();
}
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include<QPixmap>
#include<mythread.h>
#include<QThreadPool>
#include<QPainter>
timeout on t2 timer#include<QTimer>
#define REPAINT_TIME 200
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
pixmap=new QPixmap(this->size());
pixmap->fill(Qt::white);
myThread *m0=new myThread(pixmap);
QThreadPool::globalInstance()->start(m0);
//connect(m0,SIGNAL(rep()),this,SLOT(repaint()));
QTimer *qt0=new QTimer();
qt0->setInterval(REPAINT_TIME);
connect(qt0,SIGNAL(timeout()),this,SLOT(onTimeOut()));    //qt0->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.drawPixmap(0,0,*pixmap,0,0,0,0);
}
mythread.h:
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include<QPixmap>
#include<QRunnable>
class myThread:public QObject,public QRunnable
{
Q_OBJECT
public:
myThread(QPixmap *pixmap);
void run();
private:
QPixmap *pixmap;
signals:
void rep();
};
#endif // MYTHREAD_H
mythread.cpp:
#include<QPainter>
#include<QThread>
#define SLEEP_TIME_MS 100
myThread::myThread(QPixmap *pixmap):
pixmap(pixmap)
{
}
void myThread::run(){
int i=50;
while(i<100){
i++;
QPainter painter(pixmap);
painter.drawLine(100,i,200,i);
QThread::msleep(SLEEP_TIME_MS);
emit rep();
}
}
如今流⾏的图形界⾯主要有MFC、Qt、GTK,那么你觉得哪种更好⽤呢?

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。