Reputation: 57
For the project I am working on in Qt I need to make several things happen at the same time. One of these events is to take a temperature reading and display that reading in a text edit box along with a time stamp. The temp and time stamp do not display until the while loop i wrote finishes. I know the while loop is blocking it so I am trying to write a thread to display the time and temp, but can not figure out how to write to the gui from the thread.
Here is where I start the thread and the while loop
QThread cThread;
timeTempObject cObject;
cObject.DoSetup(cThread);
cObject.moveToThread(&cThread);
cThread.start();
while(flowTime > 0)
{
// set zero pin to be high while flowtime is more than 0
digitalWrite(0,1);
displayCurrentTime();
// set second pin LED to flash according to dutyCycle
digitalWrite(2,1);
delay(onTime);
// displayCurrentTime();
ui->tempTimeNoHeatMode->append(temp);
digitalWrite(2,0);
delay(offTime);
flowTime--;
}
noheatmode.h
namespace Ui {
class noheatmode;
}
class noheatmode : public QWidget
{
Q_OBJECT
public:
explicit noheatmode(QWidget *parent = 0);
~noheatmode();
private slots:
void on_startButtonNoHeatMode_clicked();
void on_noHeatModeBack_clicked();
public slots:
void displayCurrentTime();
private:
Ui::noheatmode *ui;
};
#endif // NOHEATMODE_H
timetempobject.h for the thread
class timeTempObject : public QObject
{
Q_OBJECT
public:
explicit timeTempObject(QObject *parent = 0);
void DoSetup(QThread &cThread);
public slots:
void DoWork();
};
#endif // TIMETEMPOBJECT_H
timetempobject.cpp
timeTempObject::timeTempObject(QObject *parent) :
QObject(parent)
{
}
void timeTempObject::DoSetup(QThread &cThread)
{
connect(&cThread,SIGNAL(started()),this,SLOT(DoWork()));
}
void timeTempObject::DoWork()
{
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(displayCurrentTime()));
// delay set to space out time readings, can be adjusted
timer->start(1500);
// Gets the time
QTime time = QTime::currentTime();
// Converts to string with chosen format
QString sTime = time.toString("hh:mm:ss:ms");
// displays current time in text edit box
Ui::noheatmode* noheatmode::ui->tempTimeNoHeatMode->append(sTime);
}
How do I alter my thread so it can write to the text editor in my gui?
Upvotes: 2
Views: 1609
Reputation: 98425
Since QTextEdit::append
is a slot, it's very easy to call it from other threads:
void tempTimeObject::DoWork() {
...
QMetaObject::invokeMethod(ui->tempTimeNoHeatMode, "append",
Qt::QueuedConnection, Q_ARG(QString, temp));
...
}
If you wished to execute arbitrary code, it boils down to "how to execute a functor in a given thread", with the thread being the main thread. The answers to this question provide multiple ways of doing it.
The simplest way on Qt 5 would be:
void tempTimeObject::DoWork() {
...
{
QObject signalSource;
QObject::connect(&signalSource, &QObject::destroyed, qApp, [=](QObject *){
ui->tempTimeNoHeatMode->append(text);
... // other GUI manipulations
});
} // here signalSource emits the signal and posts the functor to the GUI thread
...
}
Upvotes: 4