Use QTimer with its timeout event in another class of the project - c++

I'm using Qt 5.7 trying to use a timer with timeout event in a class named MyClass. I created a public variable of this class in mainwindow.h. I put the timer's slot connect in the constructor of MyClass, and have a function in MyClass to start the timer. But when I execute the function, the timer slot doesn't work.
I have no error in building, but I get the comment below on the application window at run time:
QObject::connect: No such slot QObject::on_timeout()
Here is my code:
The mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "myclass.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MyClass mc;
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
The mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myclass.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
mc.TimerStart();
}
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
class MyClass : public QObject
{
public:
MyClass();
TimerStart();
QTimer *timer;
public slots:
on_timeout();
};
#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"
#include <QMessageBox>
#include <QTimer>
MyClass::MyClass()
{
timer = new QTimer(this);
}
MyClass::TimerStart()
{
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
timer->start(1000);
}
MyClass::on_timeout()
{
QMessageBox msg;
msg.setText("updated");
msg.exec();
}

You forgot to add the Q_OBJECT to MyClass,
You're reentering the event loop in on_timeout.
You're setting the timer's interval multiple times.
You're connecting to the timer's signal multiple times.
You're making an implementation detail (the on_timeout slot) public.
You're pessimizing your code by manually managing the memory for QTimer.
You're including <QTimer> twice.
It's 2016 and you're not using C++11. Yes, you can use it even with Qt 4.
Here's how I'd write it:
Qt 5
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
msg.setText(QStringLiteral("updated"));
connect(&timer, &QTimer::timeout, &msg, &QMessageBox::show);
}
void MyClass::timerStart()
{
timer.start(1000);
}
Qt 4
Here I demonstrate that implementation details should be private. You could of course do as above and set the msg's text in the constructor, and connect directly to the msg's SLOT(show()).
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QTimer>
#include <QMessageBox>
class MyClass : public QObject
{
Q_OBJECT
QMessageBox msg;
QTimer timer{this};
Q_SLOT void on_timeout();
public:
explicit MyClass(QObject * parent = nullptr);
void timerStart();
};
#endif // MYCLASS_H
#include "myclass.h"
MyClass::MyClass(QObject * parent) : QObject{parent}
{
connect(&timer, SIGNAL(timeout()), SLOT(on_timeout()));
}
void MyClass::timerStart()
{
timer.start(1000);
}
void MyClass::on_timeout()
{
msg.setText("updated");
msg.show();
}

You forgot to add Q_OBJECT in your class declaration:
class MyClass : public QObject
{
Q_OBJECT
// ...
If you're using Qt 5.7, you should use the Qt5 syntax for connect:
connect(timer, &QTimer::timeout, this, &MyClass::on_timeout);
By doing so, the connection will be evaluated at compile time instead of runtime. Moreover, you can connect a signal to functions even if they are not declared as slots (so you won't need the Q_OBJECT identifier in the class declaration).
More info here.

Related

Signal emitted from QThread never received

Here are the code snippets. The thread class that will do some work:
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(QWidget* parent) : QThread(parent) {}
signals:
void results(size_t added);
private:
void run() override { emit results(7); }
};
The main window class:
class MyMain : public QMainWindow
{
Q_OBJECT
public:
MyMain(QWidget* parent = Q_NULLPTR) : QMainWindow(parent) {}
private slots:
void imagesAdded(size_t added) { qDebug() << "images added"; }
private:
void test() {
MyThread* thread = new MyThread(this);
connect(thread, &MyThread::results, this, &MyMain::imagesAdded);
connect(thread, &MyThread::finished, thread, &QObject::deleteLater);
thread->start();
}
};
In the debugger, I can see the "results" signal connects successfully and that the signal is emitted, however, it is never received.
you forgot to write something like moveToThread and exec() and ...
as I underestand from your question I write this example and run it:
In mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
class MyThread: public QThread
{
Q_OBJECT
public:
MyThread();
protected:
void run();
signals:
void results(int);
};
#endif // MYTHREAD_H
In mythread.cpp
#include "mythread.h"
MyThread::MyThread():
QThread(nullptr)
{
moveToThread(this);
}
void MyThread::run()
{
emit results(7);
exec();
}
In mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow: public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void imagesAdded(int added)
{
qDebug() << "images added" << added;
}
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
In mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mythread.h"
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MyThread *thread = new MyThread();
connect(thread, &MyThread::results, this, &MainWindow::imagesAdded);
connect(thread, &MyThread::finished, thread, &QObject::deleteLater);
thread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
The output :

QT Connect issue (subfunctions are not getting called in connect)

I'm using the Qt application. When I'm trying to call the subclass from the connect, subclass (doWork) function it's not getting called. please refer to my sample code and help me to solve the issue.
I'm using the Qt application. When I'm trying to call the subclass from the connect, subclass (doWork) function it's not getting called. please refer to my sample code and help me to solve the issue.
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "QMainWindow"
#include <QThread>
#include "Worker.h"
namespace Ui { class MainWindow; }
class MainWindow: public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow(); private:
Ui::MainWindow *ui;
QThread *thread;
Worker *worker;
signals:
void requestUpdate(int initial);
};
#endif // MAINWINDOW_H
Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
thread = new QThread();
worker = new Worker();
worker->moveToThread(thread);
connect(this, SIGNAL(requestUpdate(int)), worker, SLOT(doWork(int)));
int enc = 10;
emit requestUpdate(enc);
}
MainWindow::~MainWindow()
{
delete thread;
delete worker;
delete UI;
}
Worker.h
#ifndef WORKER_H
#define WORKER_H
#include<QObject>
class Worker: public QObject
{
Q_OBJECT
signals:
void workRequested();
public slots:
void doWork(int initial);
};
#endif // WORKER_H
Worker.cpp
#include "Worker.h"
#include <QTimer>
#include <QEventLoop>
#include <QThread>
#include <QDebug>
Worker::Worker(QObject *parent) :
QObject(parent)
{
_working =false;
_abort = false;
}
void Worker::doWork(int initial)
{
qDebug() << "initial" << endl;
}
Thanks & Regards,
Haji

Qt - Right Way to Implement Custom Signals and Slots

I have one MainWindow and one Class; I want to send data between them using custom signal and slot. I can't seem to figure it out, I need help.
Here is my code:
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <iostream>
#include "receive.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
signals:
void sendit(QString name);
private slots:
void on_send_button_clicked();
void display(QString e)
{
std::cout<<"Here is where I am called this "<<e.toStdString()<<std::endl;
}
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "receive.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
Receive *r = new Receive();
connect(this, SIGNAL(sendit(QString)), r, SLOT(display(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_send_button_clicked()
{
emit sendit(ui->lineEdit->text());
}
receive.h
#ifndef RECEIVE_H
#define RECEIVE_H
#include <iostream>
#include <QDialog>
class Receive : public QDialog
{
public:
Receive();
private slots:
void display(QString e);
};
#endif // RECEIVE_H
receive.cpp
#include "receive.h"
#include "mainwindow.h"
Receive::Receive()
{
}
void Receive::display(QString e)
{
std::cout<<"Here is where I am called this "<<e.toStdString()<<std::endl;
}
When I run this program, I get this message:
06:26:29: Starting C:\Users\Troy\Documents\build-tests-Desktop_Qt_5_14_1_MinGW_32_bit-Debug\tests.exe ...
QObject::connect: No such slot QDialog::display(QString) in ..\tests\mainwindow.cpp:11
QObject::connect: (sender name: 'MainWindow')
How do I get this done, please?
Thank you for your help.
Your slot in Receive needs to be public not private. Much the same as other class members, private slots can only be used by the class itself.
If you use the modern connect syntax you'll get a better compile time error:
connect(this, &MainWindow::sendit, r, &Receive::display);
You also need to make sure you add Q_OBJECT to every Qt class, it is missing from Receive.

Qt slot method (which is another class) not firing when emiting the signal

I know this question asked many times but still confused and cannot find a solution.
I have a MainWindow and a class.
In my class I have a signal which I emit in the method call.
Problem: Slot method is not firing.
Here is my code.
BWorker.h
#pragma once
#include <QObject>
class BWorker : public QObject
{
Q_OBJECT
public:
BWorker(QObject *parent);
~BWorker();
void doSomething();
signals:
void signalSomething();
};
BWorker.cpp
#include "BWorker.h"
BWorker::BWorker(QObject *parent)
: QObject(parent)
{
}
BWorker::~BWorker()
{
}
void BWorker::doSomething()
{
emit signalSomething();
}
QtGuiApplication1.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication1.h"
class QtGuiApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication1(QWidget *parent = Q_NULLPTR);
public slots:
void workDone();
private:
Ui::QtGuiApplication1Class ui;
};
QtGuiApplication1.cpp
#include "QtGuiApplication1.h"
#include "BWorker.h"
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
BWorker bworker(this);
connect(&bworker, SIGNAL(bworker.signalSomething), this, SLOT(workDone()));
bworker.doSomething();
}
void QtGuiApplication1::workDone() {
}
Your problem is here:
SIGNAL(bworker.signalSomething)
This is not valid and you should see a message in terminal saying that there is no such signal. The correct syntax for your case would be:
SIGNAL(signalSomething())
Please post your code by copy-pasting it. Do not edit the code: The problem could be emerged from where you edited.
The code of mine worked fine.
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void workDone();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "worker.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
Worker worker(this);
connect(&worker, SIGNAL(signalSomething()), this, SLOT(workDone()));
//connect(&worker, &Worker::signalSomething, this, &MainWindow::workDone);
worker.doSomething();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::workDone()
{
qDebug() << "Done.";
}
worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
void doSomething();
signals:
void signalSomething();
public slots:
};
#endif // WORKER_H
worker.cpp:
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::doSomething()
{
emit signalSomething();
}
Application Output:
Debugging starts
Done.
Debugging has finished
Printed out "Done." means the codes are working.

Set connect from another class in QT

I don't get it.
loginview.h
#ifndef LOGINVIEW_H
#define LOGINVIEW_H
#include <QMainWindow>
#include <QDebug>
#include <QPushButton>
class LoginView : public QWidget
{
public:
QWidget *LoginViewSetup(QWidget * wdgMain);
public slots:
virtual void LogInUser();
virtual void CreateUser();
public:
QPushButton *logInBtn;
QPushButton *createBtn;
};
#endif // LOGINVIEW_H
loginview.cpp
#include "loginview.h"
QWidget *LoginView::LoginViewSetup(QWidget * wdgMain)
{
//some code
return wdgCenter;
}
void LoginView::LogInUser()
{
//some code
}
void LoginView::CreateUser()
{
//some code
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <loginview.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QWidget * wdgMain;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
wdgMain = new QWidget(this);
LoginView LoginViewObj;
QWidget *wdgCenter = LoginViewObj.LoginViewSetup(wdgMain);
setCentralWidget( wdgMain );
connect(LoginViewObj.createBtn, SIGNAL (released()), &LoginViewObj, SLOT (CreateUser()));
}
MainWindow::~MainWindow()
{
delete ui;
}
Problem:
QObject::connect: No such slot QWidget::CreateUser() in
../proj/mainwindow.cpp:16
I tried to add Q_OBJECT to the loginview.h and then rebuild project with QMAKE. After that there is no warning about slot, but buttons still not active. Program don't jump to handle of the button in debug mode.
Please, help me to understand what's wrong? I have an object of another class LoginView and I pass this object as a reciever for a slot. Why it passes through my class and searches slot in QWidget?