Scientific Visualization with OpenGL and Qt
-
06-07-2019 - |
Question
I am trying to write an OpenGL visualization program for some scientific data using Qt. I would like to be able to use my existing program unchanged and simply be able to call the glwidget and tell it to update the data at the end of each time step. However in order to run a Qt program it appears you have to use QApplication
and then qt.run()
which blocks the cpu.
Here is the pseudo code
main()
{
..set up stuff
myVisualizer = new myGLWidget();
for(int i=0;i<1000;i++)
{
..do calculations
myVisualizer.update(new data)
}
}
I realize that I could put all of my existing code in to a QThread
and have it send a signal whenever it is done to connect to an update. It would just be easier this way. Does anybody have an idea how to solve this?
Solution
If you really don't want to investigate the threaded solution, which would be nicer all around, you can use the special-case timeout with 0. Basically, when you run a timer with a timeout of 0, it runs the appropriate code after processing the events that are currently on the event queue. So, you could set up something like this:
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;
};
And then combine it with the Qt-proper main code:
int main( int argc, char** argv )
{
QApplication app( argc, argv );
MyDialog dialog;
dialog.show();
return ( app.exec() );
}
OTHER TIPS
You can use QThread in your application and do the calculations in a seperate thread. What you have to do is to subclass the QThread and implement the run() method.
You can create a calculator class and add some signals in that class and connect the signal to your display widget's update slot (in this case QGLWidget::updateGL()).
Here is a rough example: (All you have to is to create a thread and DisplayWidget in your main() function and set the thread's 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()));
}