Scientific Visualization with OpenGL and Qt - qt

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?

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() );
}

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()));
}

Related

Qthread freezing MainWindow

I have a problem with QThread. Let's say I want to create a class-thread what will make some calculation infinite time. And if i will send a signal, thread will stop calculation and execute something.
// Class-thread
class A: public QThread
{
protected:
void run() { exec(); }
public slots:
void calc() { while (true) {do somethning}}
void display() { display something }
}
// Class Main window
class MainWindow
{
void buttonClick() {emit signalDisplay() }
}
// main file
void main()
{
A * a = new A;
a->start();
a->calc();
MainWindow w;
connect(&w, SIGNAL(signalDisplay()), a, SLOT(display()));
w.show();
}
The problem is that if i call a->calc() it's freeze the application. But I thought that It's working sepparate? Or I miss something ?
So you use the second approach of reimplementing QThread in your class A. I think you have to put your calculation code into run() function and then just call a->start(); Add some signals like A::jobDone(bool success) etc.
When you call your a->calc() directly from main thread of course it will be executed in the thread where you called it.. in this approach only run() function is executed in another thread and this must be started with a->start(). Check the docs there is nice example..
There is also another way:
class A : public QObject {
..
public slots:
void calc();
}
void main()
{
QThread workerThread;
A * a = new A;
a->moveToThread(workerThread);
a->start();
MainWindow w;
connect(&w, SIGNAL(startProcessing()), a, SLOT(calc()));
connect(a, SIGNAL(jobFinished(QByteArray)), &w, SLOT(displayInGuiResults(QByteArray)));
emit w.startProcessing();
w.show();
}

Qt add points one by one with QThread or QTimer?

I want to make a program in Qt to add points one by one, not all at once. To do that, I need to use QThread, or I can just use QTimer?
it can be done using QTimer and if it is time dependent (like every 1 second) then its the way to go. just create the timer, connect its timeout signal to your slot and it should work like a charm
You need create some class, inherited from QObject:
class QTimer;
class QList;
class Test_Timer : public QObject
{
Q_OBJECT
public:
explicit Test_Timer(QObject *parent = 0);
~Test_Timer();
private:
QList<QPoint> *lst;
QTimer *timer;
public slots:
void addPoint();
};
Ok, now we have timer variable for QTimer events, lst for store QPoint and addPoint() slot for handling your timer event.
At constructor we initialize members of class, connect timer's slot with current class slot and start timer with period 500ms:
Test_Timer::Test_Timer(QObject *parent) : QObject(parent)
{
lst = new QList<QPoint>;
timer = new QTimer;
connect(timer, SIGNAL(timeout()), this, SLOT(addPoint()));
timer->start(500);
}
Slot for adding points may look something like this:
void Test_Timer::addPoint()
{
static int number = 0;
if (lst->size() < 10) {
lst->append(QPoint(0, number++));
qDebug() << lst->size();
} else {
timer->stop();
deleteLater();
}
}
After all don't remember free resources:
Test_Timer::~Test_Timer()
{
lst->clear();
delete lst;
if (timer->isActive())
timer->stop();
delete timer;
}
I think this example will be helpful for you.

Qt Signal from QRunnable not received/not connecting

I'm writing a Qt Application in C++. I have a QRunnable running in a QThreadPool, and it sends a signal to the main thread. The problem is, the connection doesn't work: the signal is never received by the main thread, even though I've verified that the code doing the emit is indeed called. Here is my code:
My QRunnable class:
class OfflineAnalysisThread : public QObject, public QRunnable
{
Q_OBJECT
public:
void run();
void sendMessage(QString &qmsg)
{
emit threadMessageCallback(qmsg);
}
signals:
void threadMessageCallback(QString &string);
};
And the calling class (main thread):
class OfflineAnalysisMain : public QObject
{
Q_OBJECT
public:
(...)
public slots:
void threadMsg(QString &string);
};
The code that instantiates the new QRunnables and starts them:
void OfflineAnalysisMain::myFunction()
{
OfflineAnalysisThread *newTask = new OfflineAnalysisThread();
QObject::connect(newTask, SIGNAL(threadMessageCallback(QString &)), this, SLOT(threadMsg(QString &)));
QThreadPool::globalInstance()->start(newTask);
}
So, from my QRunnable's run function, I call sendMessage and then I do QApplication::exec(). I have a breakpoint on the threadMsg slot implementation in OfflineAnalysisMain.cpp, and that function is never called.
What am I doing wrong?
UPDATE:
Definition of my OfflineAnalysisThread::run() function:
void OfflineAnalysisThread::run()
{
std::string myMsg("This is my message");
sendMessage(myMsg);
QApplication::exec();
}
I have also tried without the QApplication::exec();, without success.
Remove the call to QApplication::exec() from within run(). This is ideally called from within your main function.
In order to get your code to work, I had to write the following main function:
#include <QApplication>
#include <QMetaType>
#include <offlineanalysismain.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
qRegisterMetaType<QString>("QString&");
OfflineAnalysisMain* main = new OfflineAnalysisMain;
main->myFunction();
return app.exec();
}
Note the call to qRegisterMetaType, which allows Qt to pass a QString through a signal-slot connection that cross thread boundaries.

QThread never runs/finishes before it can be used?

I have created a custom QObject class called EncodeThread, which looks as follows:
class EncodeThread : public QObject {
Q_OBJECT
public:
void set(SWSL::Video* v, QStringList f, QDir vDir);
void run();
public slots:
void encode();
signals:
void encodeProgress(int i);
private:
SWSL::Video* video;
QStringList files;
QDir videoDir;
};
As may be obvious, this class is used for encoding a video using an external library. Encode() contains the actual encoding routine, run() is a function I added while troubleshooting, though it's obviously non-functional:
void EncodeThread::run() {
if (currentThread() != this) {
// caller is in different thread.
QMetaObject::invokeMethod(this, "encode", Qt::QueuedConnection);
}
else {
encode();
}
}
The problem is when I use a QThread and the moveToThread() function on the EncodeThread instance, namely that nothing seems to happen. No data is written, and the instance never emits the signal which should save the encoded file to disk.
encThread.set(video, files, videoDir);
connect(&encThread, SIGNAL(encodeProgress(int)), cookVideoProgress, SLOT(setValue(int)));
connect(&encThread, SIGNAL(finished()), this, SLOT(videoCookEnd()));
connect(this, SIGNAL(videoEncode()), &encThread, SLOT(encode()));
encThread.moveToThread(&thread);
thread.start();
The above is how the whole setup is started. EncThread and thread variables are declared in the MainWindow class. I have made the set() function of EncodeThread call encode() after attempts to call encode() from the main thread using signals and QMetaObject failed.
I'm not new to threading, having used native Windows and Linux threads, as well as those of various cross-platform implementations, but QThreads really seem to baffle me. Any suggestions are more than welcome :)
Probably way to late to be any help to you, but here's a little demo program that puts an EncoderThread class to work. It probably doesn't quite mesh with your design (which your question only had fragments of), but it demonstrates running an object instance on its own thread and wiring 2 objects on different threads via signals/slots to let them communicate:
#include <stdio.h>
#include <QObject>
#include <QThread>
#include <QtCore/QCoreApplication>
// QSleeper is just a toy utility class that makes the
// protected QThread::sleep() family of functions
// publicly accessible. It's only use is for demo
// programs like this
class Sleeper : QThread
{
public:
static void sleep(unsigned long secs) { QThread::sleep(secs); }
static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
static void usleep(unsigned long usecs) { QThread::usleep(usecs); }
};
// an Encoder class that maintains itself on is own thread
class EncodeThread : public QObject {
Q_OBJECT
public:
EncodeThread();
public slots:
void encode();
signals:
void encodeProgress(int i);
void finished();
private:
QThread myThread;
};
EncodeThread::EncodeThread() {
moveToThread(&myThread);
myThread.start();
}
void EncodeThread::encode()
{
printf("EncodeThread::encode() on thread %u\n", (unsigned int) QThread::currentThreadId());
for (int i = 0; i < 6; ++i) {
// encode for 1 second or so
printf("EncodeThread::encode() working on thread %u\n", (unsigned int) QThread::currentThreadId());
Sleeper::sleep(1);
emit encodeProgress(i);
}
emit finished();
printf("EncodeThread::encode() - done\n");
}
// a controller to manage and monitor an EncoderThread instance
class VideoEncoderController : public QObject
{
Q_OBJECT
public:
void start();
public slots:
void setValue(int);
void encodingDone();
signals:
void encodingBegin();
};
void VideoEncoderController::start()
{
printf("VideoEncoderController::start() on thread %u\n", (unsigned int) QThread::currentThreadId());
emit encodingBegin();
}
void VideoEncoderController::setValue(int x)
{
printf("VideoEncoderController::setValue(int %d) on thread %u\n", x, (unsigned int) QThread::currentThreadId());
}
void VideoEncoderController::encodingDone()
{
printf("VideoEncoderController::encodingDone() on thread %u\n", (unsigned int) QThread::currentThreadId());
}
// a demo program that wires up a VideoEncoderController object to
// an EncoderThread
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
EncodeThread encThread;
VideoEncoderController controller;
QObject::connect(&encThread, SIGNAL(encodeProgress(int)), &controller, SLOT(setValue(int)));
QObject::connect(&encThread, SIGNAL(finished()), &controller, SLOT(encodingDone()));
QObject::connect(&controller, SIGNAL(encodingBegin()), &encThread, SLOT(encode()));
printf("hello world on thread %u\n", (unsigned int) QThread::currentThreadId ());
controller.start();
return a.exec();
}
#include "main.moc"
You must derive QThread, not QObject. run() method is an abstract method of QThread.
For future programmers I'm adding this answer. There are generally 3 approaches to multi-threading in Qt. Low Level, Reusing(lets say Mid Level) and High Level.
Low level also includes two different approaches. In Low level you can Inherit QThread class and provide the code that you want to run in parallel inside void QThread::run() override;. After calling QThread::start() on your drived class, code in run will execute.
Another approach in Low Level Multi-threading in Qt is relaying on Qt's event loops. In this way you create a class that is drived from QObject, not necessarily from QThread and then move that class to a new QThread with this. And after that you will call start() on that QThread object(this QThread object is an object of type QThread . You don't have to subclass QThread here. Just instantiate one object. It is where I believe you misunderstood in your code).
After calling start() on your QThread object, its event loop starts in another thread and signals from anywhere in your code that are connected to your QObject drived class's slots will run in that event loop in parallel as long as you don't use Qt::DirectConnection as last argument to this.
These two approaches has their own benefits and drawbacks. When sub-classing QThread and using Qthread::run(), if your code inside run is running inside a while(true) loop, one of your processor's threads will always be occupied with Qthread::run() code and not in the threadpool for other threads in your program.
The QObject::moveToThread() approach is useful for most cases. But if the QObject drived classe's slot is going to be called very frequently, like 100 or 1000 times per second, memory usage rises, due to possible arguments passed to the slot, and some of this signals may never reach the slot.

QT + How to call slot from custom C++ code running in a different thread

I am new to QT and I am doing some learning.
I would like to trigger a slot that modify a GUI widget from a C++ thread(Currently a Qthread).
Unfortunatly I get a: ASSERTION failed at: Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
here is some code:
(MAIN + Thread class)
class mythread : public QThread
{
public:
mythread(mywindow* win){this->w = win;};
mywindow* w;
void run()
{
w->ui.textEdit->append("Hello"); //<--ASSERT FAIL
//I have also try to call a slots within mywindow which also fail.
};
};
int main(int argc, char *argv[])
{
QApplication* a = new QApplication(argc, argv);
mywindow* w = new mywindow();
w->show();
mythread* thr = new mythread(w);
thr->start();
return a->exec();
}
Window:
class mywindow : public QMainWindow
{
Q_OBJECT
public:
mywindow (QWidget *parent = 0, Qt::WFlags flags = 0);
~mywindow ();
Ui::mywindow ui;
private:
public slots:
void newLog(QString &log);
};
So I am curious on how to update the gui part by code in a different thread.
Thanks for helping
stribika got it almost right:
QMetaObject::invokeMethod( textEdit, "append", Qt::QueuedConnection,
Q_ARG( QString, myString ) );
cjhuitt's right, though: You usually want to declare a signal on the thread and connect it to the append() slot, to get object lifetime management for free (well, for the price of a minor interface change). On a sidenote, the additional argument:
Qt::QueuedConnection ); // <-- This option is important!
from cjhuitt's answer isn't necessary anymore (it was, in Qt <= 4.1), since connect() defaults to Qt::AutoConnection which now (Qt >= 4.2) does the right thing and switches between queued and direct connection mode based on QThread::currentThread() and the thread affinity of the receiver QObject at emit time (instead of sender and receiver affinity at connect time).
In addition to stribika's answer, I often find it easier to use a signal/slot connection. You can specify that it should be a queued connection when you connect it, to avoid problems with the thread's signals being in the context of its owning object.
class mythread : public QThread
{
signals:
void appendText( QString );
public:
mythread(mywindow* win){this->w = win;};
mywindow* w;
void run()
{
emit ( appendText( "Hello" ) );
};
};
int main(int argc, char *argv[])
{
QApplication* a = new QApplication(argc, argv);
mywindow* w = new mywindow();
w->show();
mythread* thr = new mythread(w);
(void)connect( thr, SIGNAL( appendText( QString ) ),
w->ui.textEdit, SLOT( append( QString ) ),
Qt::QueuedConnection ); // <-- This option is important!
thr->start();
return a->exec();
}
You need to use QMetaObject::invokeMethod. For example:
void MyThread::run() {
QMetaObject::invokeMethod(label, SLOT(setText(const QString &)), Q_ARG(QString, "Hello"));
}
(The above code comes from here: http://www.qtforum.org/article/26801/qt4-threads-and-widgets.html)
I don't think you are allowed to call directly things that results in paint events from any
other threads than the main thread. That will result in a crash.
I think you can use the event loop to call things asynchronously so that the main gui thread picks up and then does the updating from the main thread, which is what cjhuitt suggests.

Resources