So, I am learning my way around QThread
and I understand it to a reasonable extent.
However, I am trying to implement a class derived from QThread to do a basic function, then emit a signal if a value has changed.
Let me post the Header
and Source
files:
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "mythread.h"
#include <QTextEdit>
#include <QPushButton>
#include <QSpinBox>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
void setGUI();
void Start_Thread();
void Stop_Thread(); //will be implemented later to stop all threads
public slots:
void Update_O1(int);
private:
MyThread *m_Thread1;
QPushButton *START;
QPushButton *STOP;
QSpinBox *L1Input;
QSpinBox *L2Input; //For when a second Thread is added
QSpinBox *L3Input; //For when a third Thread is added
QTextEdit *L1Out;
QTextEdit *L2Out; //For when a second Thread is added
QTextEdit *L3Out; //For when a third Thread is added
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <QGridLayout>
Dialog::Dialog(QWidget *parent)
: QDialog(parent), m_Thread1(new MyThread), START(new QPushButton("Start")),
STOP(new QPushButton("Stop")), L1Input(new QSpinBox), L2Input(new QSpinBox),
L3Input(new QSpinBox),L1Out(new QTextEdit),L2Out(new QTextEdit), L3Out(new QTextEdit)
{
setGUI();
connect(START, &QPushButton::clicked, this, &Dialog::Start_Thread);
connect(STOP, &QPushButton::clicked, this, &Dialog::Stop_Thread);
connect(m_Thread1, SIGNAL(NumberChanged(int)), this, SLOT(Update_01(int)));
//I know this is the old Syntax, but I don't know how else to do this...yet.
//I got a similar function to work on a different project using the same format
}
Dialog::~Dialog()
{
}
void Dialog::setGUI()
{
setWindowTitle("Three Threads");
resize(300,300);
START->setMaximumWidth(100);
STOP->setMaximumWidth(100);
L1Input->setRange(1,100);
L2Input->setRange(1,100);
L3Input->setRange(1,100);
L1Out->setReadOnly(true);
L2Out->setReadOnly(true);
L3Out->setReadOnly(true);
QGridLayout *GLout = new QGridLayout;
GLout->addWidget(START,0,1);
GLout->addWidget(STOP,0,2);
GLout->addWidget(L1Input,1,0);
GLout->addWidget(L2Input,1,1);
GLout->addWidget(L3Input,1,2);
GLout->addWidget(L1Out,2,0);
GLout->addWidget(L2Out,2,1);
GLout->addWidget(L3Out,2,2);
setLayout(GLout);
}
void Dialog::Start_Thread()
{
qDebug() << "START works"; //this is just to let me know the Start_Thread function is called properly
m_Thread1->start();
}
void Dialog::Stop_Thread()
{
}
void Dialog::Update_O1(int x)
{
qDebug() << QString::number(x);
}
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QObject>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = nullptr);
void run();
void setSnum(int); //setter function
bool Stop = false; //will be used later to stop a thread
signals:
void NumberChanged(int);
private:
int Snum = 10; //temporary value. will later implement setter to use value from GUI
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
#include <QDebug>
#include <QtCore>
MyThread::MyThread(QObject *parent)
: QThread{parent}
{
}
void MyThread::run()
{
while(!(Snum == 1))
{
QMutex mutex;
mutex.lock();
if(this->Stop) break;
mutex.unlock();
if(Snum % 2 == 0)
{
Snum /= 2;
}else{
Snum *= 3;
Snum += 1;
}
emit this->NumberChanged(Snum);
}
}
void MyThread::setSnum(int startnum)
{
Snum = startnum;
}
Lastely, a very basic main.cpp
file
#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
The problem I am facing though is that I don't seem to be getting a signal from the emit function in mythread.cpp
's run function. I am not getting an output in the qDebug() section of QtCreator
.
What am I doing wrong?
I am using Qt 6.3.0.
You have this connection:
connect(m_Thread1, SIGNAL(NumberChanged(int)), this, SLOT(Update_01(int)));
But your method is actually called like this:
void Dialog::Update_O1(int x)
Note Update_01 vs. Update_O1. They are different characters. One is zero and the other is capital 'o'.
So, you should have:
connect(m_Thread1, SIGNAL(NumberChanged(int)), this, SLOT(Update_O1(int)));
However, the best solution is to use the "new" signal-slot syntax.
connect(m_Thread1, &QThread::NumberChanged, this, &QDialog::Update_O1);
Actually, if the slot is short, you could even use a lambda:
connect(m_Thread1, &QThread::NumberChanged, this, [](int x) {qDebug() << QString::number(x);});
The major advantage of the new signal-slot syntax is that this sort of issue would be caught at compilation time rather than runtime. So, you would not potentially release your software with this bug.