start qtimer from another class faces segmentation fault - c++

I'm facing a problem using QTimer. The program closes with a segmentation fault in run time and when I exclude the "timer" from code, it runs properly. Here's the code:
Class A : public QObject, public QGraphicsPixmapItem{
Q_OBJECT
public:
A(QPixmap pic){
this->setPixmap(pic);
}
void start(){
timer = new QTimer();
timer->start(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(moveObject()));
}
public slots:
void moveObject(){
moveTimer = new QTimer();
moveTimer->start(20);
connect(moveTimer, SIGNAL(timeout()), this, SLOT(changePosition()));
}
void changePosition(){
//a couple of things are done here
}
private:
QTimer *timer;
QTimer *moveTimer;
}
Class B : QGraphicsView{
Q_OBJECT
public:
B(QWidget *parent = 0) : QGraphicsView(parent){
a = new A(QPixmap("a.png"));
void go(){
a->start();
}
private:
A *a;
}
P.S. I delete moveTimer in changePosition as long as the object stops moving and recall moveObject so that it can move towards the next target.

Related

How to connect signal from a different class?

// splashscreen.h
class SplashScreen : public QMainWindow
{
Q_OBJECT
public:
explicit SplashScreen(QWidget *parent = nullptr);
~SplashScreen();
QTimer *mtimer;
public slots:
void update();
private:
Ui_SplashScreen *ui;
};
// app.h
#include "splashscreen.h"
class App: public QMainWindow
{
Q_OBJECT
public:
App(QWidget *parent = nullptr);
~App();
SplashScreen s;
private:
Ui::AppClass ui;
};
// app.cpp
App::App(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QGraphicsOpacityEffect* eff = new QGraphicsOpacityEffect();
s.centralWidget()->setGraphicsEffect(eff);
QPropertyAnimation* a = new QPropertyAnimation(eff, "opacity");
a->setDuration(2000);
a->setStartValue(0);
a->setEndValue(1);
a->start(QPropertyAnimation::DeleteWhenStopped);
s.show();
connect(a, &QAbstractAnimation::finished, this, [this]
{
auto *timer = new QTimer();
this->s.mtimer = timer;
QObject::connect(timer, SIGNAL(timeout()), this->s, SLOT(update()));
timer->start(100);
});
}
I'm getting an error at this line: QObject::connect(timer, SIGNAL(timeout()), this->s, SLOT(update()));
no instance of overloaded function "QObject::connect" matches the argument list
I think it's mismatching the class signal, as this passed to the lambda refers to App not SplashScreen.
When i try to pass s (SplashScreen) to the lambda:
connect(a, &QAbstractAnimation::finished, this, [s]
{ ... }
I get an error: App::s is not a variable.
I'm confused, what is the proper way to connect in this case?
In App class, s is an instance, not a pointer to an instance. Function connect needs pointer, not reference.
Use these syntax should help:
QObject::connect(timer, &QTimer::timeout, &s, &SplashScreen::update);
Use these syntax:
QObject::connect(timer, &QTimer::timeout, this, &SplashScreen::update);

Bypassing Qt signaling to avoid class-to-class signaling

I'm trying to figure out how I could work with Qt signals in a little bit different way.
I have a working example of such:
Game::Game(QObject *parent)
: QObject{parent}
, m_timer{nullptr}
{
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &Game::run);
m_timer->setinterval(300);
m_timer->start();
}
Above signaling works fine and calls the Game::run regularly as desired. Now I am trying to replicate this with this bypass (for the sake of learning and it could be useful for more complicated moments especially in unit testing)
Abstract class:
class ISignalHandler
{
public:
virtual void onTimeout() = 0;
protected:
virtual ~ISignalHandler() = default;
};
and another class MyTimer.cpp:
MyTimer::MyTimer(QTimer *parent)
: QTimer{parent}
{
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &MyTimer::onTimeout);
}
MyTimer::~MyTimer()
{
delete m_timer;
m_timer = nullptr;
}
void MyTimer::registerTimerSignal(ISignalHandler* callback)
{
m_callback = callback;
}
void MyTimer::onTimeout()
{
if (m_callback != nullptr)
{
m_callback->onTimeout();
}
}
and finally Game class:
//header:
class Game : public QObject, public ISignalHandler
{
Q_OBJECT
public:
explicit Game(QObject *parent = nullptr);
~Game();
//cpp:
Game::Game(QObject *parent)
: QObject{parent}
, m_timer{nullptr}
{
m_timer = new MyTimer();
m_timer->registerTimerSignal(this);
m_timer->setinterval(300);
m_timer->start();
}
void Game::onTimeout()
{
run();
}
I expected that the MyTimer class will repeat within itself, and the signal will be handled to Game class so ::run will be continuously called. Where is a mistake here?

how to stop the Qtimer upon a condition

when i executing this Qtimer it says "invalid use of 'this' in non-member function"
QTimer *timerStart( )
{
QTimer* timer = new QTimer( );
Ball *b = new Ball();
QObject::connect(timer,SIGNAL(timeout()),b,SLOT(move()));
//timer->start( timeMillisecond );
timer->start(15);
return timer;
}
my ball.h file
class Ball: public QObject, public QGraphicsRectItem{
Q_OBJECT
public:
// constructors
Ball(QGraphicsItem* parent=NULL);
// public methods
double getCenterX();
public slots:
// public slots
void move();
private:
// private attributes
double xVelocity;
double yVelocity;
int counter = 0;
QTimer timerStart( );
// private methods
void stop();
void resetState();
void reverseVelocityIfOutOfBounds();
void handlePaddleCollision();
void handleBlockCollision();
};
#endif // BALL_H
the move() function is in the same class. what i want to do is stop the returned timer upon a if condition is satisfied.
when i issue this code in Ball::Ball constructor in Cpp it works fine. the ball is moving.
QTimer* timer = new QTimer();
timer->setInterval(4000);
connect(timer,SIGNAL(timeout()),this,SLOT(move()));
timer->start(15);
but when i add Qtimer *timerStart beyond the Ball::Ball constructor, iT doesnt work
Declare the QTimer as a member in you class
h file:
class Ball: public QObject, public QGraphicsRectItem{
{
Q_OBJECT
public:
// constructor
Ball(QGraphicsItem* parent=Q_NULLPTR);
// control your timer
void start();
void stop();
...
private:
QTimer * m_poTimer;
}
Initiate the timer object in your constractor
cpp file:
Ball::Ball(QGraphicsItem* parent) :
QGraphicsItem(parent)
{
m_poTimer = new QTimer(this); // add this as a parent to control the timer resource
m_poTimer->setInterval(4000);
connect(m_poTimer,SIGNAL(timeout()),this,SLOT(move()));
}
void Ball::start()
{
// start timer
m_poTimer->start();
}
void Ball::stop()
{
// stop timer
m_poTimer->stop();
}

Is it possible to create many QProgressDialogs objects, that will show progress different long operations?

I have class, that launches tasks in separate thread:
class SomeTask : public QObject, QRunnable
{
Q_OBJECT
signals:
void updateProgressBar(int, int);
public:
SomeTask(int, QWidget*);
void run();
void runLongOperation(QString)
{
QThreadPool::globalInstance()->start(this);
}
};
And in MainWindow I create for every long calculation new QProgressBar
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
QList<QProgressDialog*> m_listProgressDialogs;
public slots:
void handle(QString)
{
m_listProgressDialogs.push_back(new QProgressDialog("Task in progress...", "Cancel", 0, 100));
m_listProgressDialogs.at(m_listProgressDialogs.size()-1)->show();
SomeTask *task = new SomeTask(m_listProgressDialogs.size()-1, this);
QObject::connect(mv, SIGNAL(updateProgressBar(int)), this, SLOT(setValueProgressBar(int)));
task->runLongOperation(......);
}
void setValueProgressBar(int);
};
Is it possible to create new QProgressBar for every long task and every task will emit the signal to set value in specific QProgressBar. Is it good to store QProgressBar* in QList, like I wrote ?

QtNetwork: Why don't I detect incomming connections ? (incomingConnection() is never fired)

I sticked to the tutorial about threaded qt-networking (which is here: http://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html), I made some minor changes and integrated it into my main program. However incomingConnection() never gets executed, on the other hand the client is able to connect. Since I'd like to work with incomingConnection() it became obsolete to work with the SIGNAL(newConnection()) but even this isn't working.
Somebody knows what's going wrong?
Here my .h
#include <QtNetwork>
#include <QTcpServer>
#include <QTcpSocket>
#include <QThread>
class WirelessNetThread: public Thread
{
Q_OBJECT
public:
WirelessNetThread(int socketDescriptor, QObject * parent);
void run() Q_DECL_OVERRIDE;
signals:
void error(QTcpSocket::SocketError socketError);
private:
int socketDescriptor;
QString text;
};
class WirelessNet : public QTcpServer
{
Q_OBJECT
public:
WirelessNet(QObject *parent = 0);
protected:
void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;
};
And the .cpp
WirelessNetThread::WirelessNetThread(int socketDescriptor, QObject *parent):QThread(parent), socketDescriptor(socketDescriptor)
{
}
void WirelessNetThread::run()
{
QTcpSocket tcpSocket;
if ( !tcpSocket.setSocketDescriptor(socketDescriptor))
{
emit error(tcpSocket.error());
return;
}
tcpSocket.disconnectFromHost();
tcpSocket.waitForDisconnected();
}
WirelessNet::WirelessNet(QObject *parent): QTcpServer(0)
{
listen(QHostAddress::Any, 5220);
printf("is listening %d\n", this->isListening());
}
void WirelessNet::incomingConnection(qintptr socketDescriptor)
{
qDebug() << "incomming \n";
printf("incomming \n");
WirelessNetThread *thread = new WirelessNetThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
here the excerpt out of my main program, where it is initiated (by the way it doesn't matter if I leave out moveToThread():
WirelessNet *wifi = new WirelessNet(this->parent());
wifi->moveToThread(this->thread());
Even this has no influence if I add these lines after the initalization of wifi:
wifi = new WirelessNet(this->parent());
QEventLoop testLoop;
testLoop.exec();
In other words "incomming" is never printed out, and so I'm not able to work on. Has anyone an idea, this is pretty much 1:1 the code from the tutorial that's what confuses me.
In your main code:
WirelessNet *wifi = new WirelessNet(0); // 0 = assign no parent
QThread *wifiThread = new QThread;
wifi->moveToThread(wifiThread);
QObject::connect(wifiThread, SIGNAL(started()), wifi, SLOT(startWifi()));
// start() will start its own event loop, it will emit started(), therefore startWifi() slot will be called.
wifiThread->start();
Then your WirelessNet class header:
class WirelessNet : public QTcpServer
{
Q_OBJECT
public:
WirelessNet(QObject *parent = 0);
protected:
void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;
public slots:
void startWifi();
};
Then your WirelessNet class body:
WirelessNet::WirelessNet(QObject *parent) :
QTcpServer(parent)
{
// Do nothing much here because we want to initialise new stuff in our thread.
// When this function runs we have not moved this to the new thread - or even started it.
}
void WirelessNet::incomingConnection(qintptr socketDescriptor)
{
qDebug() << "incomming \n";
printf("incomming \n");
WirelessNetThread *thread = new WirelessNetThread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
// Called when the thread has started
void WirelessNet::startWifi()
{
// Anything done here is now safely within out new thread.
listen(QHostAddress::Any, 5220);
printf("is listening %d\n", this->isListening());
}
note this is example code, I wrote it directly into stack overflow it has not been compiled, so there are probably some errors :) There are some key points, that I have commented, where you may have gone wrong in your original attempt.