I am trying to create an event that gets fired off every n seconds in my Singleton worker. A signal/slot connection (with the signal being the QTimer timing out and the slot being a lambda function which makes a call to another Singleton class) is not working. The connect call is succeeding, the timer is active, and I get no QTimer complaints on the console. If I try to print QTimer's remaining time it reads -1. For the life of me, I cannot figure out why "timeout" is never being printed (indicating that the event is being triggered). Any help would be greatly appreciated. For simplicity's sake we can assume that OtherSingleton has the same structure. I should also note that this Singleton class object is running inside of a QThread.
Singleton.h:
#include <QObject>
#include <string>
#include <QTimer>
#include <QThread>
class Singleton : public QObject
{
Q_OBJECT
public:
static Singleton& get_instance();
Singleton(Singleton const&) = delete;
void operator=(Singleton const&) = delete;
static void stop_client();
static void start_client();
private:
Singleton();
static QTimer bytes_timer_;
};
Singleton.cpp:
#include "Singleton.h"
#include <QDebug>
#include <QTime>
#include <QFile>
Singleton::Singleton()
{
bytes_timer_.setParent(this);
bytes_timer_.moveToThread(QThread::currentThread());
bytes_timer_.setInterval(1000);
qDebug() << "Timeout success:" << connect(&bytes_timer_, &QTimer::timeout, this, [&]() {
qDebug() << "timeout";
// . . .
}, Qt::DirectConnection);
}
Singleton& Singleton::get_instance() {
static Singleton instance;
return instance;
}
void Singleton::start_client() {
bytes_timer_.start();
}
void Singleton::stop_client() {
bytes_timer_.stop();
}
QTimer Singleton::bytes_timer_;
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QThread>
#include "singleton.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
QThread thread;
Singleton *s;
Ui::MainWindow *ui;
};
#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);
s = &Singleton::get_instance();
s->moveToThread(&thread);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
thread.start();
s->start_client();
}
main.cpp:
#include "mainwindow.h"
#include <QApplication>
#include <QThread>
#include "singleton.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
QTimer
cannot work if there is no main loop which processes events. The latter is e.g. part ofQApplication::exec()
. Do you call it? – Scheff's Catbytes_timer_.moveToThread(QThread::currentThread());
makes me afraid. What is it good for? (Timers and threads are just another topic which is good for trouble...) If timer shall be fired from a thread (I'm not sure why this should be necessary), then this thread needs an event loop too. I found a Qt wiki article about this: Threads Events QObjects. – Scheff's Cat