2

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?

p.i.g.
  • 2,815
  • 2
  • 24
  • 41
cdbean04
  • 57
  • 1
  • 8
  • 2
    Can you focus this a bit and make it more a question? – Glenn Teitelbaum Jul 01 '15 at 20:23
  • As @GlennTeitelbaum said, that's not very clear. But in principle, why you just send from your thread a signal with the text, and catch it in your main thread to update te gui? – Miki Jul 01 '15 at 21:28

1 Answers1

4

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
  ...
}
Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313