QThread updating a Widget in the GUI
-
wrote on 23 Mar 2015, 10:58 last edited by
Good day
I am writing an application which has to update a QLable with info from a QThread in real time. I am stuck at the point where only the last emit is received by the QLable, for some reason. Here is my code:
#ifndef RANDWALK_H #define RANDWALK_H #include <QThread> #include <QStringList> #include <QTime> #include <QDebug> class RandWalk : public QThread { Q_OBJECT public: RandWalk(); public slots: void generateCoordinates(int steps, QStringList start); signals: void message(QString); private: int x; int y; }; #endif // RANDWALK_H #include "randwalk.h" RandWalk::RandWalk() { } void RandWalk::generateCoordinates(int steps, QStringList start) { int startX = start.at(0).toInt(); int startY = start.at(1).toInt(); QTime time = QTime::currentTime(); int seed = time.msec(); QStringList rList; qsrand(seed); for(int i = 0; i < steps; i++) { rList << QString::number(qrand() + startX) + ", " + QString::number(qrand() + startY); qDebug() << rList.at(i); emit message(rList.at(i)); this->sleep(1); } } #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); walker1 = new RandWalk; walker1->start(); connect(walker1, SIGNAL(message(QString)), ui->locationLbl, SLOT(setText(QString))); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_goBtn_clicked() { QStringList start1; start1 << ui->xLedt->text() << ui->yLedt->text(); walker1->generateCoordinates(10, start1); } ` Your help will be much appreciated. Thank you
-
wrote on 23 Mar 2015, 11:04 last edited by
Usually Qt tries to "compact" the refresh requests; this is to avoid flickering.
You could try to manually call
QWidget::repaint()
in a slot -
Usually Qt tries to "compact" the refresh requests; this is to avoid flickering.
You could try to manually call
QWidget::repaint()
in a slotwrote on 23 Mar 2015, 11:40 last edited by sleroux@mcosta
Thanks for the reply. I am not sure that this is the problem, because I have increased the sleep intervals in my iteration in the Thread to 5 seconds, and the label still only updates on the last one.
Also, there is no place to call repaint() from, in my current program structure. What I mean is that the signal is emitted from the walker object, which also dictates the intervals. -
wrote on 23 Mar 2015, 12:36 last edited by
I suggest to create a custom slot in you class and call setText and repaint from there; in that way you can be able to detect how often the signal is received
void MainWindow::mySlot(const QString &text) { qDebug() << Q_FUNC_INFO; ui->locationLbl->setText(text); ui->locationLbl->repaint(); }
connect(walker1, SIGNAL(message(QString)), this, SLOT(mySlot(QString)));
-
wrote on 23 Mar 2015, 15:50 last edited by
It looks like your RandWalk thread isn't actually running. You are calling generateCoordinates() from the GUI thread, so it's holding up the program there. That explains why you only see the last update.
The QThread documentation shows a couple different ways to do work in another thread:
http://doc.qt.io/qt-5/qthread.html -
I suggest to create a custom slot in you class and call setText and repaint from there; in that way you can be able to detect how often the signal is received
void MainWindow::mySlot(const QString &text) { qDebug() << Q_FUNC_INFO; ui->locationLbl->setText(text); ui->locationLbl->repaint(); }
connect(walker1, SIGNAL(message(QString)), this, SLOT(mySlot(QString)));
wrote on 26 Mar 2015, 05:12 last edited by sleroux@mcosta
Good day
Apologies for only replying now - we had an internet outage...
Just after my last reply I tried your previous suggestion (to manually call QWidget::repaint() ) out a bit more, and it worked.
Thank you very much! -
As @Dyami-Caliri said your program is not using the thread at all.
You are calling bothgenerateCoordinates()
andrepaint()
in the ui thread. There's no parallel execution here.
1/7