使用 OpenGL 和 Qt 进行科学可视化

Posted

技术标签:

【中文标题】使用 OpenGL 和 Qt 进行科学可视化【英文标题】:Scientific Visualization with OpenGL and Qt 【发布时间】:2009-06-18 02:52:58 【问题描述】:

我正在尝试使用 Qt 为一些科学数据编写一个 OpenGL 可视化程序。我希望能够原封不动地使用我现有的程序,并且能够简单地调用 glwidget 并告诉它在每个时间步骤结束时更新数据。但是,为了运行 Qt 程序,您似乎必须使用QApplication,然后使用qt.run(),它会阻塞 cpu。

这是伪代码

main()


    ..set up stuff
    myVisualizer = new myGLWidget();

    for(int i=0;i<1000;i++)
    
        ..do calculations
        myVisualizer.update(new data)
    
   

我意识到我可以将所有现有代码放入 QThread 并让它在连接到更新时发送一个信号。这样会更容易。有人知道如何解决这个问题吗?

【问题讨论】:

【参考方案1】:

如果您真的不想研究线程解决方案,这会更好,您可以使用 0 的特殊情况超时。基本上,当您运行超时为 0 的计时器时,它会运行处理当前在事件队列中的事件后的适当代码。所以,你可以这样设置:

class MyDialog : public QDialog

    Q_OBJECT
public:
    MyDialog()
    
        m_step = 0;
        QTimer::singleShot( 0, this, SLOT( Process() ) );
    

public slots:
    void Process() 
    
        // do calculations
        m_step++;
        QTimer::singleShot( 0, this, SLOT( Redraw() ) );
        if ( m_step != 1000 )
            QTimer::singleShot( 0, this, SLOT( Process() ) );
    

    void Redraw()  // do redrawing code here 

private:
    int m_steps;
;

然后将它与 Qt-proper 的主代码结合起来:

int main( int argc, char** argv )

    QApplication app( argc, argv );
    MyDialog dialog;
    dialog.show();
    return ( app.exec() );

【讨论】:

赞成这个答案,因为我会这样做。不需要单独的线程。但是我不认为重绘插槽需要单次计时器,以及为什么小部件是 QDialog 的子类而不是 QGLWidget。【参考方案2】:

您可以在应用程序中使用 QThread 并在单独的线程中进行计算。 你要做的就是继承 QThread 并实现 run() 方法。

您可以创建一个计算器类并在该类中添加一些信号,然后将信号连接到显示小部件的更新槽(在本例中为 QGLWidget::updateGL())。

这是一个粗略的例子:(你所要做的就是在你的 main() 函数中创建一个线程和 DisplayWidget 并设置线程的 DisplayWidget。)

class Calculator: public QObject

     Q_OBJECT

     public:
        Calculator();
        void start();

    signals:
        void updateDisplayWidget(/* you can put the resulting data */);
;

class DisplayWidget(): public QGLWidget

     Q_OBJECT
     // override paint methods here
     public slots:
          void slotUpdateDisplayWidget(/* you can receive the resulting data*/);
;

class MyThread : public QThread

public:
    void run();
    void setDisplayWidget(DisplayWidget* displayWidget);

private:
    Calculator mCalculator;
;

void MyThread::run()

     mCalculator.start();
     exec();


MyThread::setDisplayWidget(DisplayWidget* displayWidget)

    displayWidget->moveToThread(this);
    connect(&mCalculator, SIGNAL(updateDisplayWidget()), displayWidget, SLOT(slotUpdateDisplayWidget()));

【讨论】:

DisplayWidget 中的插槽不会在 QThread 的上下文中运行吗? 不,Qt 主事件循环处理线程,一切都会正常工作。

以上是关于使用 OpenGL 和 Qt 进行科学可视化的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 启动 Unity(解耦控制和可视化)

带有 OpenGL 的 Qt MDI 应用程序:如何获取有效的屏幕截图?

从 OpenGL C 程序生成视频

QXcbIntegration:无法创建平台 OpenGL 上下文,GLX 和 EGL 均未启用

关于opengl和 osg的问题

OpenGL ES之实现实时音频的可视化