cdbean04
cdbean04

Reputation: 57

How in Qt to add text to a text editor using a thread

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

Answers (1)

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

Related Questions