我想渲染一个三角形,其坐标由一个单独的线程不断更新(使用m_offset)。该线程在整个运行时间内并行运行。
我的应用程序使用GL小部件初始化QT窗口。
#include "mainwindow.h"
#include <QApplication>
#include <iostream>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
GL小部件(glwidget.cpp)定义如下:
#include "glwidget.h"
#include <iostream>
#include <thread>
GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{
m_offset = 0.0
// HERE, I want to start a thread on updateCoordinates().
// Something like this: (this doesn't work)
//std::thread mythread (updateCoordinates);
// or this (getting segfault)
//std::thread mythread (&GLWidget::updateCoordinates, this);
}
void GLWidget::initializeGL()
{
glClearColor(0.2, 0.2, 0.2, 1);
}
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1,0,0);
glVertex3f(-0.5+m_offset, -0.5+m_offset, 0);
glColor3f(0,1,0);
glVertex3f(0.5+m_offset, -0.5+m_offset, 0);
glColor3f(0,0,1);
glVertex3f(0.0+m_offset, 0.5+m_offset, 0);
glEnd();
}
void GLWidget::resizeGL(int w, int h)
{}
void GLWidget::updateCoordinates()
{
while(true)
{
m_offset += 0.0001;
}
}
以下是相应的标题:
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget *parent = 0);
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
void startSimulation();
void stopSimulation();
void updateCoordinates();
private:
double m_offset;
signals:
public slots:
};
#endif // GLWIDGET_H
如何在此类中继续运行updateCoordinates()
的新线程,同时通过paingGL()
更新图形?
谢谢!
答案 0 :(得分:1)
您可以使用QtConcurrent::run
在单独的线程中运行函数。
QFuture<void> future = QtConcurrent::run(this,&GLWidget::updateCoordinates );
在您的updateCoordinates()
函数中,您可以发出一个名为repaint
的信号,该信号与QGLWidget::updateGL
相关联,以调用paintGL()
函数:
void GLWidget::updateCoordinates()
{
while(true)
{
m_offset += 0.0001;
emit repaint();
}
}
请注意,repaint()
信号应与updateGL
连接,且连接类型为Qt::BlockingQueuedConnection
。
你的while循环中应该还有一个标志,它被检查以终止while和线程。
您可以检查未来代表的异步计算的状态,如:
if(future.isRunning())
{
// It is currently running
}
或者等待它完成:
future1.waitForFinished();
答案 1 :(得分:1)
您可以使用QThread。
虽然存在其他选项,例如QConcurrent,但有些question its implementation。
创建一个从QObject派生的对象,它将负责更新坐标。每次更新后,对象都可以发出一个带坐标的信号,然后在主线程上接收回来。
class Worker : public QObject
{
Q_OBJECT
public:
Worker();
~Worker();
public slots:
void process();
signals:
typedef QVector<QPoint> PointList;
void NewCoordinates(PointList points);
private:
PointList m_pointList;
private:
};
Worker::Worker() {
// you could copy data from constructor arguments to internal variables here.
}
// --- DESTRUCTOR ---
Worker::~Worker() {
// free resources
}
// --- PROCESS ---
// Start processing data.
void Worker::process() {
// calculate new coordinates...
emit NewCoordinates(m_pointList);
}
从主线程设置并启动线程和工作器实例..
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
// tidy up
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
// assuming we're in the MainWindow class, with a NewCoordinates slot function
// collect points - C++ 5 connect syntax
connect(worker, &Worker::NewCoordinates(Worker::PointList), this, &MainWindow::NewCoordinates(Worker::PointList);
// let's go
thread->start();
void MainWindow::NewCoordinates(Worker::PointList pointList)
{
// handle updated coordinates
}
要了解如何真正地,真正地使用QThread,有一篇很棒的文章here。