2014-10-22 44 views
0

比方說,我想要使用兩個線程呈現動畫三角形。一個線程操縱頂點,另一個線程管理QT窗口並呈現GL上下文。我有一個類cTriangle,其中成員Eigen::Vector3d m_A, m_B, m_C代表三角形頂點,以及在頂點上操作的方法void updateCoordinates()GL頂點數據的QThread數據共享方法

cTriangle.h:

#ifndef CTRIANGLE_H 
#define CTRIANGLE_H 

#include <Eigen/Core> 
#include <QObject> 
#include <vector> 

class cTriangle : public QObject 
{ 
    Q_OBJECT 

public: 
    cTriangle(); 

public: 

    Eigen::Vector3d m_A; 
    Eigen::Vector3d m_B; 
    Eigen::Vector3d m_C; 

public slots: 
    void updateCoordinates(); 

}; 

#endif // CTRIANGLE_H 

cTriangle.cpp:

#include "cTriangle.h" 
#include <iostream> 

cTriangle::cTriangle() 
{ 
    m_A = Eigen::Vector3d(0.0, 0.0, 0.0); 
    m_B = Eigen::Vector3d(0.2, 0.0, 0.0); 
    m_C = Eigen::Vector3d(0.0, 0.2, 0.0); 
} 

void cTriangle::updateCoordinates() 
{ 
    int ctr = 0; 
    double t = 0.0; 

    while (true) 
    { 
     std::cout << "cTriangle::updateCoordinates " << ctr << std::endl; 
     double offset = 0.3*sin(t); 
     m_A = Eigen::Vector3d(offset, 0.0, 0.0); 
     t += 0.00001; 
     ctr++; 
    } 
} 

驅動程序創建一個新的cTriangle並啓動的QThread,其中不斷循環超過updateCoordinates()。我也初始化包含GLWidget的MainWindow。

main.cpp中:

int main(int argc, char *argv[]) 
{ 

    cTriangle* tri = new cTriangle(); 

    QThread* thread = new QThread; 
    tri->moveToThread(thread); 
    QObject::connect(thread, SIGNAL(started()), tri, SLOT(updateCoordinates())); 
    thread->start(); 


    QApplication a(argc, argv); 
    MainWindow w; 
    w.show(); 

    return a.exec(); 
} 

glwidget.h:

#ifndef GLWIDGET_H 
#define GLWIDGET_H 
#include <QGLWidget> 
#include "cTriangle.h" 

class GLWidget : public QGLWidget 
{ 
    Q_OBJECT 
public: 
    explicit GLWidget(QWidget *parent = 0); 
    void initializeGL(); 
    void resizeGL(int w, int h); 

private: 

signals: 
    void repaint(); 

public slots: 
    void paintGL(); 

}; 

#endif // GLWIDGET_H 

glwidget.cpp:

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) 
{ 


} 

void GLWidget::initializeGL() 
{ 
    glClearColor(0.2, 0.2, 0.2, 1); 
} 
void GLWidget::paintGL() 
{ 
    std::cout << "paintGL " << std::endl; 

    // ******************************** 
    // How do I access Triangle data here?? 
    // ******************************** 


    glClear(GL_COLOR_BUFFER_BIT); 

    glLoadIdentity(); 

    glBegin(GL_TRIANGLES); 
     glColor3f (1,0,0); 
     glVertex3f (0, -0.5, 0); 
     glColor3f (0,1,0); 
     glVertex3f (0.5, -0.5, 0); 
     glColor3f (0,0,1); 
     glVertex3f (0.0, 0.5, 0); 
    glEnd(); 

} 
void GLWidget::resizeGL(int w, int h) 
{} 

最後,我的問題:我需要訪問頂點數據GLWidget::painGL之內的對象tri。這樣做的最好方法是什麼?設置信號插槽功能?以線程安全的方式傳遞tri的指針(如果是這樣,如何?)。這只是一個玩具的例子,通常頂點數據可能非常大。謝謝!!

=============================

一步:

我現在的計劃設置設置信號 - >信號 - >插槽機制。 GLWidget::glPaint()發出SIGNAL GLWidget::requestVertices()到另一個SIGNAL cTriangle::sendVertices(whateverType vertexData),然後由SLOT GLWidget::receiveVertices(whateverType vertexData)收到。在main.cpp中,我如何連接這些信號?我如何獲得對GLWidget對象的引用? QObject::connect(???, SIGNAL(requestVertices()), tri, SIGNAL(sendVertices(double arg)));

回答

1

首先使用信號和插槽機制。如果你發出一個帶有QList的信號,QList使用implicit sharing,所以只有在寫時複製。

這是在線程間使用數據的最簡單方法,不需要您處理任何鎖。如果在某些時候你覺得這太慢了,那麼你可以考慮優化代碼來提高速度。

一種可能的優化方法是使用多個QList的點,所以你寫入一個,然後繼續寫下一個,然後發出第一個,以確保你沒有寫入共享列表並因此最小化發生寫入時複製的機會。

但是,沒有必要進行優化,除非您首先看到問題。

+0

Thanks @ Merlin069。我現在的計劃是設置一個信號 - >信號 - >插槽機制。 GLWidget :: glPaint()向另一個SIGNAL'cTriangle :: sendVertices(whateverType vertexData)'發出SIGNAL'GLWidget :: requestVertices()',然後由SLOT'GLWidget :: receiveVertices(whateverType vertexData)'接收。 主要。CPP,我如何連接這些信號?我如何獲得對'GLWidget'對象的引用? QObject :: connect(???,SIGNAL(requestVertices()),tri,SIGNAL(sendVertices(double arg))); – user2926577 2014-10-22 23:31:47

+0

在StackOverflow中,您最好一次提出一個問題。你能接受這個答案嗎?如果答案是可以接受的,請刪除「更進一步」部分並開始一個新問題?這樣做也會使您對第二個問題有更大的瞭解,而不是隱藏在第一個問題後面。 – TheDarkKnight 2014-10-23 07:56:24