updating QLabel in non-GUI thread continuously - multithreading

I access the Qt GUI's QLabel's QPixmap in another thread since I will finally use this to display mjpeg stream in QLabel, and I decided to use QLabel since its the easiest way
It should look like 'Live' and not block the UI thus using another (non-gui) thread.
nothing shows up in the QLabel. only the exception QPixmap: It is not safe to use pixmaps outside the GUI thread
any better or correct way to do this ?
here is my PyQt code of another thread: self.theQlabel.setPixmap(QtGui.QPixmap.fromImage(myQimg)

Instead of directly setting the pixmap, make the external thread emit an updatePixmap signal. Then in the GUI thread, listen to the signal and update the pixamp at that time. Something like that should work (in C++):
// In the GUI thread:
class YourWidget: QObject {
public:
YourWidget();
public slots:
void updatePixmap(const QPixmap& pixmap);
}
YourWidget::YourWidget() {
// Connect to the signal here:
QObject::connect(otherThread, SIGNAL(updatePixmap(const QPixmap&)), this, SLOT(updatePixmap(const QPixmap&)));
}
YourWidget::void updatePixmap(const QPixmap& pixmap) {
// Update the pixmap here in a thread-safe way
}
// In the external thread:
// Emit the signal. The GUI thread will receive it and can then update the pixmap
emit updatePixmap(thePixmap);

I think that it might be dangerous to even create a QPixmap in anything other than the GUI thread. You might want to consider passing a QImage and converting it to a QPixmap in the main thread. I can't find a direct reference to support this assertion, but
http://developer.qt.nokia.com/doc/qt-4.8/thread-basics.html
hints that
All widgets and several related classes, for example QPixmap, don't work in secondary threads.
The email thread at
http://lists.trolltech.com/qt-interest/2008-11/msg00534.html
also seems to agree with me.

Create RAW DirectX/OpenGL OS context into this QLabel's winId() and do whatever you want. I think, this is the best way for high performance HD video, and the ONLY way :) sometimes you just HAVE to use RAW things to achieve the maximum performance and touch the iron in your computer :)

Related

Boost asio with Qt

I am trying to use boost::asio async client example with a simple Qt GUI like:
A little snippet from my app:
The button click SLOT:
void RestWidget::restGetCall()
{
networkService ntwkSer("www.boost.org","80");
connect(&ntwkSer, SIGNAL(responseReady(std::string)), this, SLOT(showResponse(std::string)));
ntwkSer.get("/LICENSE_1_0.txt");
}
The networkService class is just a wrapper of the above linked boost sample code.Its derived from QObject class for signal,slot mechanism.
void networkService::get(const std::string & path)
{
// boost::thread (boost::bind(&networkService::networkCall,this,path));//this gives me sigabrt
networkCall(path);//this works fine, and i get output as pictured above.
}
void networkService::networkCall(const std::string path)
{
tcp::resolver::query query(host_, port_);//also these host,port fields come out to be invalid/garbage.
//tcp::resolver::query query("www.boost.org","80");//still doesnt resolve the SIGABRT
resolver_.async_resolve(query,
boost::bind(&networkService::handle_resolve, this,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator,
path));
io_service.run();
}
The problem, is when i run the io_service.run() from the boost::thread. i get SIGABRT.
also he host_,port_ networkService wrapper class fields inside the networkService::networkCall(path) function on debugging come out to be invalid, which get saved while constructing:
networkService ntwkSer("www.boost.org","80");
The obvious reason for boost::thread is to make GUI non-blocking,since io_service() has its own eventloop. My intention is to run boost::asio async calls in a seperate boost thread, and notify the GUI thread with QT's Q_OBJECT signal slot mechanism.
I don't get the reason of SIGABRT and also why could the field values of host_ and port_ become invalid once i start using boost::thread.
PS: This same setup, behaves correctly with boost::thread from a similar commandline application (no Qt GUI code), i.e when the networkService class is not hacked for Qt signal/slot to notify the main GUI thread. Here, i use the boost::asio's response from within the boost::thread.
Edit:
as per responses to my question, i tried this... i disabled Q_OBJECT signal/slot and QObject derivation of the networkservice class, to be sure MOC isnt messing things up.. but still, the issue prevails, i get access violation on windows vs sigabrt on linux. The issue of the networkservice object's fields getting corrupted is also present, eventually getting access violation.
In effect no change in behaviour.
before launching thread:
from inside thread
access violation on continue...
So, even without MOC , the issue is still there.
Edit 2:
Im sorry for bothering.. i did a huge mistake, of using a local networkService object from within the boost::thread, which got scoped out when the thread actually ran!
It's difficult to get the asio io_service.run() function to "play well" with the Qt event loop.
It's easier to use a Qt slot that calls io_service::poll() or io_service::poll_one() and then connect that slot to a QTimerEvent.
And it's even easier to use QNetworkAccessManager instead of asio see Qt Client Example
The problem is that with qt only one thread is allowed to manipulate the gui in qt. That is the one calling QApplication::exec. This is done to remove complexity for the users of qt and due to that QApplication / message loop being a singleton. That being said there is some magic going on in qt with threads. All QObjects are assigned a thread. By default the one on which they are created. When a signal slot connection is made it is determined how to actually dispatch the call. If the objects belong to the same thread a signal is dispatched by directly / synchronous invoking the slot. If the objects are assigned to distinguished threads a message is send from one thread to another to invoke the slot on the thread that is assigned to the object where the slot lives. This is what you actually need here.
The problem with your code is that both of your QObjects are created on the same thread. They are therefore assigned the same thread. So the slot which manipulates the GUI is called directly from your worker thread and remember this is prohibited! Since your worker is not the one calling QApplication::exec. To override the automatics and convince to correctly do the thread switch when calling the slot you must use Qt::QueuedConnection when doing the connect.
connect(&ntwkSer, SIGNAL(responseReady(std::string)), this, SLOT(showResponse(std::string)), Qt::QueuedConnection);

MFC: how to draw opengl from a different thread?

I am trying to do some opengl 1.0 animation in a CWnd window with 60 fps. I create a sub class of CWnd:
class COpenGLControl : public CWnd
{
...
}
I found if I use the build-in timer "setTimer()" and set it to fire on every 1000/60 ms, all the opengl commands were able to render correctly. However, If I implement my own timer using a separate thread, nothing is drawn. All I got was a black screen.
Is there a way to issue opengl commands from a different thread?
Even if you are not intending to issue GL calls from multiple threads, you have to take OpenGL's rules for threading into account: An OpenGL context can only be used by at most one thread at a time. (And, per thread, there can be at most one active GL context at any time). That does not mean that you cannot use the same context in multiple threads, or create it in one and use it in another, you just have to explicitely "hand over" the context from one thread to another.
I don't know if you use some further librariy for GL context handling, so I'm assuming you are using the native API of your OS - in this case wgl. The relevant function is wglMakeCurrent(). So, to hand over a context which is "current" in thread A to thread B, thread A must first call wglMakeCurrent(NULL,NULL) before thread B can get the context via wglMakeCurrent(someDC, myGLCtx). You can of course switch around a GL context as many times you like, but that will introduce a huge synchronization overhead and should be avoided.
From your comments:
Would work If I create the context also in the timer thread?
Yes, it would.
Just a side note: Creating is not the issue here at all, since creating a GL context does not automatically make it "current" to a thread - so you can just create it in thread A and afterwards make it current directly to thread B.

Qt signals and slots with threaded class

I have a QWidget TableView class that displays tables, calculates data etc...
Inside its costructor I start FortuneServer server of the class:
FortuneServer::FortuneServer(QObject *parent)
: QTcpServer(parent)
{
...
This class starts a new thread on FortuneServer::incomingConnection that looks like:
FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent)
: QThread(parent), socketDescriptor(socketDescriptor), text(fortune)
{
}
void FortuneThread::run()
{
QTcpSocket tcpSocket;
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket.error());
cout<<"socket error"<<endl;
return;
}
tcpSocket.waitForReadyRead(10000);
// this where sockets opens and waits for incoming data...
I need to do the folowing:
I need to connect the string I get in this thread from the client, with some function inside TableView class that calculates another string and returnes it back into this thread and send it to the client.
If I use emit from the thread, how do I make the thread wait for result?
How is this done correctly?
ty
When reading bytes from a source on the network you can :
1- Use a binary message with a fixed length. So you can wait for blocks of bytes to be read and do whatever you need to do with it.
2- Use a string based protocol which uses delimiters for separating the messages. When a delimiter is seen you need to extract a new income message.
3- Use something like Content Length to know how many bytes have come and you should read.
in Qt, you need to have a slot in the Called class. As well a signal in the Caller class. When a new string is arrived(using whatever method) you simply emit the signal and the called classes will get notified. You have to use connect() method to connect slot to signal. I think QIODevice which is a parent for QTcpSocket has a signal named readyRead() which gives you the signal when new data are available.
Never do operations which are probable to throw exceptions in a constructor. It is better to make and start server out of the constructor in a different method.
I think the best way to do this would be not to start a separate thread, but rather give your socketDescriptor int to a QSocketNotifier object (of type QSocketNotifier::Read) and connect the QSocketNotifier's activate(int) signal to a slot in your GUI's class. Then whenever bytes become ready-for-read from the network, your slot will be called in the main thread and you can read them and deal with them there, without having to work about inter-thread messaging or signaling or blocking issues. Much easier that way :)

QPointer in multi-threaded programs

According to http://doc.qt.io/qt-5/qpointer.html, QPointer is very useful. But I found it could be inefficient in the following context:
If I want to show label for three times or do something else, I have to use
if(label) label->show1();
if(label) label->show2();
if(label) label->show3();
instead of
if(label) { label->show1();label->show2();label->show3(); }
just because label might be destroyed in another thread after label->show1(); or label->show2();.
Is there a beautiful way other than three ifs to get the same functionality?
Another question is, when label is destroyed after if(label), is if(label) label->show1(); still wrong?
I don't have experience in multi-threaded programs. Any help is appreciated. ;)
I think the only safe way to do it is to make sure you only access your QWidgets from within the main/GUI thread (that is, the thread that is running Qt's event loop, inside QApplication::exec()).
If you have code that is running within a different thread, and that code wants the QLabels to be shown/hidden/whatever, then that code needs to create a QEvent object (or a subclass thereof) and call qApp->postEvent() to send that object to the main thread. Then when the Qt event loop picks up and handles that QEvent in the main thread, that is the point at which your code can safely do things to the QLabels.
Alternatively (and perhaps more simply), your thread's code could emit a cross-thread signal (as described here) and let Qt handle the event-posting internally. That might be better for your purpose.
Neither of your approaches is thread-safe. It's possible that your first thread will execute the if statement, then the other thread will delete your label, and then you will be inside of your if statement and crash.
Qt provides a number of thread synchronization constructs, you'll probably want to start with QMutex and learn more about thread-safety before you continue working on this program.
Using a mutex would make your function would look something like this:
mutex.lock();
label1->show();
label2->show();
label3->show();
mutex.unlock()
As long as your other thread is using locking that same mutex object then it will prevented from deleting your labels while you're showing them.

How to run parallel codes using QT?

I am developing a simulator. I have chosen QT for the GUI. My project involves a lot of manipulation of data and I use QT just to plot my results.
My code structure is such that my main function contains a global object of my data, an object of the QT GUI and other objects for manipulating this data. I need to modify this data at every 30 ms. I have also attached a simplified version of my main file.
My problem is that I cannot call functions of my other objects (other than the GUI) before exiting the QT object. I have implemented timers in QT in isolation which plots the new data and works fine. All I want to do is call my ai and phySim object at a particular time interval independant of the QT object. I want these three objects to be completely independent.
world* _world;
int main(int argc, char *args[])
{
_world = new world();
gui *GUI; ///QT object
ai *AI;//object to manipulate data
phySim *sim;//object to manipulate data
/////////////////////////////////// this gets executed only when i close the QT gui
AI = new ai(_world);
AI->doSomething();
sim = new phySim(_world);
sim->updateWorld();
//////////////////////////////////////////////////////////////////////////////
QApplication app(argc,args);
GUI = new gui(_world);
GUI->show();
return app.exec();
}
Take a look at the Signals and Slots in Qt. Connect a "closed" signal that you emit when you close your GUI to a "startThread" slot. Have your AI and Simulation running in separate threads and if they need to interact, make use of signals/slots again.
You say you want the three objects to be "completely independent" -- then you should give each of them their own thread.
Maybe you should try not not run the app.exec(), but instead create a custom (almost) infinite loop, call processEvents() within that loop and your updateWorld() plus a wait of 30ms (or a little less, due to the function execution will take some ms). Drawing is then part of Qt (you should pass the instance of your simulator and add a render method (maybe best in pure OpenGL, as this can be passed through the Qt layer via a QGLWidget). Call that method within paint() or respectivly paintGL() for QGLWidget I hope this helps (a little), you should read QGLWidget doc
Note: You will have to write some wrappers in form of signals, calling your simulationObj methods, otherwise no UI interaction will be possible within Qt.
I was going to suggest overriding some event methods on QApplication but event loops can be tricky since you have some "child loops" http://labs.trolltech.com/blogs/2010/02/23/unpredictable-exec. In one of the 2009 Tech talks on there is a part that explains this too.
One approach is to separate your GUI a bit more by using a Client Server architecture. Your sim can be the server and Qt GUI the client. There are some nice samples in Qt using sockets.
Another approach is to use QTimer to update (or poll) your Sim. You might not even need threads.
void SomeGUI::SomeGUI(..)...
{
//Init sim
m_World = new world();
m_AI = new ai(m_World);
m_Sim = new phySim(m_World);
...
//Connect timer
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateWorld()));
timer->start(100); //or whatever interval works
...
}
void SomeGUI::updateWorld()
{
//Update sim state
m_AI->doSomething();
m_Sim->updateWorld();
updateGUI();
}

Resources