Program crashes because of wrong usage of slots and signals - c++

What I'm trying to do is to call an time consuming operation (MockClamWrapper::loadDatabase()) in a separate thread at the moment of creation of my window and then to update my window once the operation is completed. Here is the code that I have.
MockClamWrapper.h
class MockClamWrapper : QObject
{
Q_OBJECT
public:
MockClamWrapper();
~MockClamWrapper();
bool loadDatabase(unsigned int *signatureCount=NULL);
Q_SIGNALS:
void databaseLoaded();
};
MockClamWrapper.cpp
bool MockClamWrapper::loadDatabase(unsigned int *signatureCount){
QThread::currentThread()->sleep(10);
databaseLoaded();
return true;
}
MainWindow.h
#include <QMainWindow>
#include <QFileDialog>
#include "mockclamwrapper.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void enableWindow();
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
MockClamWrapper *clam;
void initWindow();
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect((QObject*)clam, SIGNAL(databaseLoaded()),(QObject*)this,SLOT(enableWindow()));
QFuture<void> fut = QtConcurrent::run(this,&MainWindow::initWindow);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initWindow(){
clam->loadDatabase(NULL);
}
void MainWindow::enableWindow(){
ui->checkFileButton->setEnabled(true);
}
The program compiles, but it crashes right after start. I assume that I do something wrong with slots and signals, but can't find my mistake.

The reason for crash is that you are not making any instance of the class MockClamWrapper. In the connect statement, you are referencing a pointer that points to nothing. Make a new object and then connect :
clam = new MockClamWrapper();
connect(clam, SIGNAL(databaseLoaded()), this, SLOT(enableWindow()));

Related

No such slot MainWindow::showPreferencesWindow()

I will be glad if you could help me a little.
So as it is in topic I have error trying to do Q_OBJECT::connect.
So my code is:
preferences.h:
#include <QDialog>
#include <QApplication>
#include <QCoreApplication>
namespace Ui {
class Preferences;
}
class Preferences : public QDialog
{
Q_OBJECT
public:
explicit Preferences(QWidget *parent = 0);
~Preferences();
private:
Ui::Preferences *ui;
};
preferences.cpp:
#include "preferences.h"
#include "ui_preferences.h"
Preferences::Preferences(QWidget *parent) :
QDialog(parent),
ui(new Ui::Preferences)
{
ui->setupUi(this);
}
Preferences::~Preferences()
{
delete ui;
}
mainwindow.h:
#include "preferences.h"
#include "addkierowca.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Preferences *PreferencesWindow;
private:
/* some private methods */
void showPreferencesWindow();
And last but not least mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->actionUstawiania, SIGNAL(triggered()), this, SLOT(showPreferencesWindow()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showPreferencesWindow()
{
PreferencesWindow = new Preferences(this);
PreferencesWindow->show();
PreferencesWindow->exec();
}
I couldn't found anwser anywhere, and I know that there are almost same topics, but none of them helped me.
Thanks in advice.
You are using showPreferencesWindow as a slot in the connect so need to at it to a slot.
change to:
private slots:
void showPreferencesWindow();
At that point, moc (used by the makefile) will generate the correct code needed for connect to work correctly.

Qt5 won't send timeout signal

I'm new to QT5, and I'm having a very strange problem.
I want to use QTimer to read coordinate from serial device every 0.5 second, but the QTimer won't send timeout signal.
My .h:
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void test();
private:
Ui::MainWindow *ui;
};
My .cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer myTimer(this);
myTimer.setInterval(500);
myTimer.setSingleShot(false);
connect(&myTimer, SIGNAL(timeout()), this, SLOT(test()));
myTimer.start();
}
void MainWindow::test() {
qDebug() << "Time out";
}
MainWindow::~MainWindow()
{
delete ui;
}
After I started the program, not a single "Time out" shows up...
I added the following codes after "myTimer.start()":
QTime t = QTime::currentTime().addMSecs(550);
while (QTime::currentTime() < t) {
qDebug() << myTimer.remainingTime();
}
And I found that after the remaining time of "myTimer" reduced to 0, it won't refill the remaining time and start once again, it remains at 0.
Q_OBJECT is already added
Anyone got an idea?
Thank you very much!
The problem is here:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer myTimer(this);
myTimer.setInterval(500);
myTimer.setSingleShot(false);
connect(&myTimer, SIGNAL(timeout()), this, SLOT(test()));
myTimer.start();
}
In the constructor you declared myTimer automatically, so it will be destroyed as soon as constructor returns. This way, by the time when you expect timeout event, myTimer does not exist anymore and thus it cannot send any signals!
The solution is straightforward: myTimer should exist all the time MainWindow object lives, so declare it in the class, not in it's constructor, and allocate it dynamically:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void test();
private:
QTimer *myTimer; // <--- pointer declaration.
Ui::MainWindow *ui;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Allocating actual QTimer object:
myTimer = new QTimer(this);
// Calling methods by object pointer:
myTimer->setInterval(500);
myTimer->setSingleShot(false);
connect(myTimer, SIGNAL(timeout()), this, SLOT(test()));
myTimer->start();
}
MainWindow::~MainWindow()
{
// Don't forget to delete after usage.
delete myTimer;
delete ui;
}
myTimer is local.
Make it a class member and use it. It will work.

Cannot execute a slot which should change GUI in Qt

I am trying to implement signal/slot connection which will show alert in editLine. I have no idea why the slot is not executing.
I tried: connect(mKlient, SIGNAL(showInfo(QString)), qApp, SLOT(aboutQt()));
To be sure that the signal is working correctly. So I think that something is wrong with the slots. Below is the code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <klient.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Klient *mKlient;
private:
Ui::MainWindow *ui;
public slots:
void onShowInfo(QString);
private slots:
//void on_pushButton_clicked();
void on_pushButtonConnect_clicked();
};
#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);
onShowInfo("This alert is working"); // works
//-------------------Here is the signal/slot connection-------------------------------------
mKlient = new Klient(this);
connect(mKlient,SIGNAL(showInfo(QString)),this, SLOT(onShowInfo(QString))); //not working - no idea why :/
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onShowInfo(QString text){
ui->lineEdit->setText(text);
}
void MainWindow::on_pushButtonConnect_clicked()
{
if(ui->radioButtonTCP->isChecked()){
mKlient->disconnect(this);
mKlient->connectToServer(ui->lineEditIpAddress->text(), ui->lineEditTcpPort->text().toInt());
}
}
klient.h
#ifndef KLIENT_H
#define KLIENT_H
#include <QObject>
#include <QTcpSocket>
#include <QAbstractSocket>
class Klient : public QObject
{
Q_OBJECT
public:
explicit Klient(QObject *parent = 0);
void connectToServer(QString,int);
bool isConnectedFlag;
signals:
void showInfo(QString);
public slots:
void connected();
private:
QTcpSocket *mSocket;
};
#endif // KLIENT_H
klient.cpp
#include "klient.h"
Klient::Klient(QObject *parent) :
QObject(parent)
{
isConnectedFlag = false;
}
void Klient::connectToServer(QString address, int port){
mSocket = new QTcpSocket(this);
connect(mSocket, SIGNAL(connected()),this,SLOT(connected()));
mSocket->connectToHost(address,port);
if(!mSocket->waitForConnected(1000)){
//error mSocket->errorString();
}
}
void Klient::connected(){
emit showInfo("Connected"); //this information should be on lineEdit
mSocket->write("siemanko"); //executing properly
isConnectedFlag = true;
}
}
I was following this tutorial to find a bug, but no results:
https://samdutton.wordpress.com/2008/10/03/debugging-signals-and-slots-in-qt/
Am I doing something wrong? I am new to Qt so maybe accessing to the GUI is more complicated than I thought.
I found the answer...
In
void MainWindow::on_pushButtonConnect_clicked()
{
if(ui->radioButtonTCP->isChecked()){
mKlient->disconnect(this);
mKlient->connectToServer(ui->lineEditIpAddress->text(), ui->lineEditTcpPort->text().toInt());
}
}
I thought that I am disconnecting TCP connection. Unfortunatelly I was disconnecting signal/slot connection.
Should I delete my question ? How to do this ?

QT program crashes after connect()

I'm trying to write my new app, but it crashes every time I press a button on QDialog.
Here's my code :
mainwindow.h
#include <QMainWindow>
#include "creatlist.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QDialog* creatList;
public slots:
void tableFull(){
...some code here...
}
private:
Ui::MainWindow *ui;
};
creatlist.h :
#include <QDialog>
#include "mainwindow.h"
namespace Ui {
class creatlist;
}
class MainWindow;
class creatlist : public QDialog
{
Q_OBJECT
public:
explicit creatlist(QWidget *parent = 0);
~creatlist();
MainWindow* mainwindow;
signals:
void updateList();
public slots:
void ready(){
///////////////////////////////////////////////////////////crash
connect(this,SIGNAL(updateList()),mainwindow,SLOT(tableFull()));
emit updateList();
}
private:
Ui::creatlist *ui;
};
If i try to send some signals my app crashes with a Segmentation Fault.
I did:
void creatlist::ready()
{
mainwindow = new MainWindow(this);
emit mainwindow->linktableFull();
}
but if I try to do QTextBroser.append("hue hue"); in linktableFull(), QTextBrowser is always empty.
Your QTextBrowser always empty because you create new mainwindow object in every ready() function. You should create mainwindow object once and use same mainwindow object throughout code. You can create new mainwindow object in creatlist constructor.

Qt: Calling MainWindow::Ui from another class using signals and slots

I made a simple Qt project to cover the issue of calling Ui from another class.
The Files:
mainwindow.h | mainwindow.cpp | client.h | client.cpp | main.cpp
The Issue:
Connecting a signal from client.cpp to a slot in mainwindow.cpp worked very well.
But when I added a ui->statusBar->showMessage("message");
in the slot, it didn't work.
NOTE: When I made the signal and the slot both in mainwindow.cpp it worked, but calling a slot from mainwindow.cpp from a signal and connect() in client.cpp doesn't work.
The Codes: (trimmed to the essentials)
mainwindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
public slots:
void doSomething();
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::doSomething()
{
QMessageBox::information(0, "test", "BINGO!!");
ui->statusBar->showMessage("testing");
}
client.h
class client : public QObject
{
Q_OBJECT
public:
explicit client(QObject *parent = 0);
void call();
signals:
void connected();
public slots:
};
client.cpp
client::client(QObject *parent) :
QObject(parent)
{
MainWindow main;
connect(this, SIGNAL(connected()), &main, SLOT(doSomething()));
call();
}
void client::call()
{
emit connected();
}
Added:
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Thanks.
client::client(QObject *parent) :
QObject(parent)
{
MainWindow main;
connect(this, SIGNAL(connected()), &main, SLOT(doSomething()));
call();
}
Your MainWindow lives on the stack. I think by the time your doSomething slot is triggered, the MainWindow object is already long gone. Try creating your MainWindow on the heap instead.
I see a major mistake in the code you have posted.
You have created an instance of MainWindow in the file main.cpp and thats the window you see when you run the application. But in your client.cpp you are creating a second instance of MainWindow and connecting the signal from the client object to the slot of the second MainWindow object you create. You are not seeing two main windows because you do not run the exec or show methods of this second instance.
Now coming to the solution, you will have to connect the signal from client to the proper MainWindow instance. I will suggest two methods below.
First:
I believe you create an instance of client in one of the member functions of the class MainWindow. If so then shift the connect method to the file mainwindow.cpp
Something like:
void MainWindow::someFunction()
{
client* c = new client();
connect(c, SIGNAL(connected()), this, SLOT(doSomething()));
c->call();
}
Second:
If you cannot do what is explained above, then you can use a combination of a static pointer and a static function to get the instance of MainWindow. Note that this method can also be used to ensure that there is only one instance of MainWindow at any given time.
mainwindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
public slots:
void doSomething();
public:
explicit MainWindow(QWidget* parent = 0);
~MainWindow();
static MainWindow* GetInstance(QWidget* parent = 0);
private:
Ui::MainWindow *ui;
static MainWindow* mainInstance;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow* MainWindow::mainInstance = 0;
MainWindow* MainWindow::GetInstance(QWidget *parent)
{
if(mainInstance == NULL)
{
mainInstance = new MainWindow(parent);
}
return mainInstance;
}
void MainWindow::doSomething()
{
QMessageBox::information(0, "test", "BINGO!!");
ui->statusBar->showMessage("testing");
}
Now in whatever class you need to get the instance of MainWindow in use, simply use the static function MainWindow::GetInstance to get the pointer to the MainWindow instance and use that as the parameter for connect.
i.e.,
MainWindow* instance = MainWindow::GetInstance();
client* c = new client();
connect(c, SIGNAL(connected()), instance , SLOT(doSomething()));