I work in Qt and when I press the button GO I need to continuously send packages to the network and modify the interface with the information I receive.
The problem is that I have a while(1)
in the button so the button never finishes so the interface is never updated. I thought to create a thread in the button and put the while(){}
code there.
My question is how can I modify the interface from the thread? (For example how can I modify a textBox from the thread ?
Qt offers many classes and functions for working with threads. Below are four different approaches that Qt programmers can use to implement multithreaded applications.
Graphical user interfaces often have a dedicated thread (“GUI thread”) for servicing user interactions. The thread must remain responsive to user requests even while the application has long computations running. For example, the user might want to press a “cancel” button to stop the long running computation.
To use it, prepare a QObject subclass with all your desired functionality in it. Then create a new QThread instance, push the QObject onto it using moveToThread(QThread*) of the QObject instance and call start() on the QThread instance. That's all.
As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads.
Important thing about Qt is that you must work with Qt GUI only from GUI thread, that is main thread.
That's why the proper way to do this is to notify main thread from worker, and the code in main thread will actually update text box, progress bar or something else.
The best way to do this, I think, is use QThread instead of posix thread, and use Qt signals for communicating between threads. This will be your worker, a replacer of thread_func
:
class WorkerThread : public QThread { void run() { while(1) { // ... hard work // Now want to notify main thread: emit progressChanged("Some info"); } } // Define signal: signals: void progressChanged(QString info); };
In your widget, define a slot with same prototype as signal in .h:
class MyWidget : public QWidget { // Your gui code // Define slot: public slots: void onProgressChanged(QString info); };
In .cpp implement this function:
void MyWidget::onProgressChanged(QString info) { // Processing code textBox->setText("Latest info: " + info); }
Now in that place where you want to spawn a thread (on button click):
void MyWidget::startWorkInAThread() { // Create an instance of your woker WorkerThread *workerThread = new WorkerThread; // Connect our signal and slot connect(workerThread, SIGNAL(progressChanged(QString)), SLOT(onProgressChanged(QString))); // Setup callback for cleanup when it finishes connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); // Run, Forest, run! workerThread->start(); // This invokes WorkerThread::run in a new thread }
After you connect signal and slot, emiting slot with emit progressChanged(...)
in worker thread will send message to main thread and main thread will call the slot that is connected to that signal, onProgressChanged
here.
P.s. I haven't tested the code yet so feel free to suggest an edit if I'm wrong somewhere
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With