SIGSEGV with QMainWindow singleton - qt

The application I am writting as unique instantiation of some classes which have to be accessible easily. For that i use singletons.
For exemple my Core is defined as :
class Core : public QObject
{
Q_OBJECT
public:
Core();
~Core();
static Core& getCore()
{
static Core mycore;
return mycore;
}
(...)
};
and it works just great. However I tried to do the same with my MainWindow class, which interits from QMainWindow. I need that in order to access methods such as geometry() from other objects
However Core works great, MainWindow makes error when clossing the programe. The main window destructor is called and executed apparently once ( debug using qDebug() ) but i still have a SIGSEGV signal. What's happening? How to solve it?
Here is the code of MainWindow
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
static MainWindow& getUi()
{
static MainWindow myUi;
return myUi;
}
public slots:
void refreshImage();
private:
Ui::MainWindow *ui;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(&appCore(), SIGNAL(refreshed()), this, SLOT(refreshImage()));
}
MainWindow::~MainWindow()
{
delete ui;
}
And the main code
QApplication app(argc, argv);
try
{
appCore().setDevice(MDMA::Kinect);
appUi().show();
return app.exec();
} catch(MDMA::exn e) {
(...)
}
where appCore and appUi are macros for Core::getCore and MainWindow::getUi()

This crash probably results from your QApplication being destroyed before the MainWindow.
If you cannot pass your MainWindow via other ways to the code where it is needed (e.g. as argument or via QObjecg::parent()), you could employ a technique similar to what QApplication does with it's instance method (a non-owning global reference):
Construct your MainWindow as an ordinary local variable on the stack, after the QApplication. Then set a global pointer (maybe better a QPointer; e.g. a static member of MainWindow), which you initially initialize to 0, to this in the constructor of MainWindow. You can also check if it was already initialized here to enforce the uniqueness. Via a public accessor method (instance?) for the global pointer, you can access the class from everywhere while ensuring destruction before QApplication.

If you want to make singletone, try to use general technics, for example, as described here:
http://www.qtcentre.org/wiki/index.php?title=Singleton_pattern
Hope, lot of questions will dissappear after reading all of that article.
As for me, there is nice and simple realization of singletone.
Good luck!

Related

How can I connect a signal to QWidget::update slot?

I am using Qt5 with new signal/slot syntax.
I don't know why the following code doesn't work:
QWidget *widget = new QWidget();
connect(pipeline, &Pipeline::NewFrame, widget, &QWidget::update);
I get the error:
no matching member function for call to 'connect' why?
Pipeline class inherits from QObject and NewFrame signal has the same signature as QWidget::update
class Pipeline
: public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Pipeline)
public:
Pipeline(QObject *parent);
signals:
void NewFrame();
};
I am using QtCreator on Arch Linux with g++.
TL;DR: The pipeline should be signaling an image, and the widget should have a SetImage method:
class Pipeline : public QObject {
Q_OBJECT // important
public:
Q_SIGNAL void NewFrame(const QImage &);
...
};
class Viewer : public QWidget {
Q_OBJECT // important
QImage m_image;
public:
Q_SLOT void SetImage(const QImage &image) {
m_image = image;
update();
}
...
};
This is how you'd be using it - note that Viewer knows nothing about Pipeline, because it shouldn't: it just shows new frames, wherever they come from.
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Pipeline pipeline;
Viewer viewer;
QObject::connect(&pipeline, &Pipeline::NewFrame, &viewer, &Viewer::SetImage);
return app.exec();
}
Connecting anything to QWidget::update directly, especially from external sources, is usually a sign of bad design.
To satisfy your curiosity, you can use a lambda or qOverload to specify what you're connecting to, to fix the very error you're seeing - caused by ambiguity of the the type of the method pointer. Any of the following will work:
connect(…, widget, qOverload<>(&QWidget::update));
or
auto constexpr update = qOverload<>(&QWidget::update));
connect(…, widget, update);
or
connect(…, widget, [widget]{ widget->update(); });

Qt Model and View - Link data from model to view, how?

I'm pretty new to the Model and View concept and I'm having trouble finding the right way to do this. So in my understanding the concept means, that I have one class that handles all the view (GUI) parts and an other class which handles the data processing.
The GUI I made has a few Display Widgets (LCDnumbers) which just have to get data from the other class and output it into the LCD.
So I made a function in the GUI class which can set a number into the LCD. And I've made a function which can change the value of the number in the data class.
Now I need something to connect those, for example when I change the number in the data class I want it to update in the GUI. I found somethings about Signals and Slots (and emitting a signal) but how does that work, while maintaining the Model and View concept?
It could be that this is answered somewhere else, if so, can you link me the source? I couldn't find anything to solve my problem.
Thanks for reading and I hope someone can help me.
Header file of the GUI:
#include <QMainWindow>
#include <QtCore>
namespace Ui {
class MainBoardView;
}
class MainBoardView : public QMainWindow
{
Q_OBJECT
public:
explicit MainBoardView(QWidget *parent = 0);
~MainBoardView();
void ChangeNumber(int value);
private:
Ui::MainBoardView *ui;
};
CPP file of the GUI:
#include "mainboardview.h"
#include "ui_mainboardview.h"
MainBoardView::MainBoardView(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainBoardView)
{
ui->setupUi(this);
}
MainBoardView::~MainBoardView()
{
delete ui;
}
void MainBoardView::ChangeNumber(int value)
{
ui->lcdNumber->display(value);
}
Code of the data class:
Header:
class MainBoard
{
public:
MainBoard();
void changeMoney(int value);
private:
int m_money;
}
CPP:
void MainBoard::ChangeMoney(int value)
{
m_money = value;
//emit a signal here with the value to the ChangeNumber function of the GUI?
//and how should I do this?
}
For applying model/view concept of Qt you should use at least one of a model classes. Such model classes provide unified interface for several types of data (string-list, trees, sql, etc.)
For displaying the data one would use either a view-class or widgets connected to the model via QDataWidgetMaper
In your case there is no use of model/view observable. MainBoard should be QObject for emitting the signal:
class MainBoard: public QObject
{
Q_OBJECT
public:
MainBoard();
void changeMoney(int value); //emit value with emit moneyChanged(value) in the implementation.
signals:
void moneyChanged(int)
private:
int m_money;
}

What is the delete sequence of QObject with default parent in Qt?

The Qt Doc says if a QObject has a parent, then when the parent is deleted, it will also delete all its children.
However, if I have multiple QObjects with the default parent (0), when will they be deleted?
And what will be the sequence of deleting?
If we're talking about pointers to QObject, no, they won't be deleted. You will have a memory leak unless you delete them manually so there won't be any sequence of deleting.
Pointers don't release their memory unless delete is called on them. Say you have a pointer to a memory location to which no other pointer points. If that pointer goes out of scope and you don't call delete on it, you will have a memory leak because if no other pointer points to that memory location then you won't have access to that memory location anymore. And you get an inaccessible and useless chunk of memory.
In classes, destructors have the purpose of releasing the memory when deleted. Destructors are called when instances of the classes go out of scope(in case of instances allocated on the stack i.e. static, e.g. MyClass x;) or when delete is called of them(in case of pointers i.e. dynamic, e.g. MyClass *x = new MyClass;)
Qt created a clever mechanism so that programmers won't have to think that much of these things because lots of errors occur because of them. So Qt introduced parents, i.e. if you set a QObject a parent, when you will delete the parent the QObject will be deleted as well.
If you use QObject pointers as members in a class and don't set them a parent, when an instance of that class gets deleted you will have a memory leak unless, of course, you delete them manually in the destructor.
For example the following implementation will create memory leak if used:
class MyObject : public QObject
{
public:
MyObject(QObject *parent = 0);
~MyObject();
private:
QTimer *m_pTimer;
}
MyObject::MyObject(QObject *parent) : QObject(parent)
{
m_pTimer = new QTimer; // memory leak when this will be destroyed
}
MyObject::~MyObject()
{
}
In order to fix this you should provide this as parent:
MyObject::MyObject(QObject *parent) : QObject(parent)
{
m_pTimer = new QTimer(this);
}
or
MyObject::~MyObject()
{
delete m_pTimer;
}
In an implementation like this:
class MyObject : public QObject
{
public:
MyObject(QObject *parent = 0);
~MyObject();
private:
QTimer m_timer;
}
MyObject::MyObject(QObject *parent) : QObject(parent)
{
// Do stuff
}
MyObject::~MyObject()
{
}
where you don't have pointers and memory allocated on the heap, all the members are destroyed when getting out of scope i.e. when the instance of the class(in our case MyObject) gets out of scope.
I consider worth mentioning here the layouts system in Qt.
Lets say you have a QWidget with a QPushButton inside it. If you create a QLayout, add the QPushButton to the QLayout and set the QLayout on the QWidget with QWidget::setLayout, automatically a child-parent relationship will be created between the QPushButton and the QWidget and also between the QLayout and the QWidget.
Here's an example:
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
QGridLayout *m_pLayout;
QPushButton *m_pButton;
};
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
m_pLayout = new QGridLayout;
m_pButton = new QPushButton;
m_pButton->setText("Push me!");
m_pLayout->addWidget(m_pButton, 0, 0);
setLayout(m_pLayout); // In this moment *this* will be automatically
// set as parent for both m_pLayout and m_pButton
// even though no parent was passed to their constructors.
}
Widget::~Widget()
{
}
I hope this helps.

connect QPushButton via lambda

I am trying to connect QPushButton to lambda expression:
QPushButton* loadTextFileButton = new QPushButton("load");
connect(loadTextFileButton, &QPushButton::clicked, [](){
qDebug()<<"clicked";
});
Compiler gives me an errors like: No matching function to call "MyClass::connect(..."
What I am doing wrong?
The connect function, which is part of Qt's signal and slots mechanism is Qt's extension to C++.
The connect function is actually a static function of QObject, so you can use it from anywhere, by simply including QObject: -
#include <QObject>
...
QObject::connect(itemPtr1, SIGNAL(someFunction()), itemPtr2, SLOT(someOtherFunction());
The objects itemPtr1 and itemPtr2 are pointers to instances of classes that are derived from QObject and support signals and slots.
In order for a class to use the signal and slot mechanism, it must inherit from QObject and declare the Q_OBJECT macro:-
class MyClass : public QObject
{
Q_OBJECT // the Q_OBJECT macro, which must be present for signals and slots
public:
MyClass(QObject* parent);
signals:
public slots:
private:
void StandardFunction();
};
As this class inherits QObject, it now has direct access to the connect function, allowing calling connect directly:-
QPushButton* loadTextFileButton = new QPushButton("load");
connect(loadTextFileButton, &QPushButton::clicked, []()
{
qDebug()<<"clicked";
});
Finally, Qt 5 introduced a new syntax for signals and slots: -
connect(loadTextFileButton, &QPushButton::clicked, this, &MyClass::StandardFunction);
You may have noticed that the advantage here is that the signal can be connected to a function that is not declared as a slot. In addition, using this syntax provides compile time error checking.

Qt subclassing from QWidget

I write my own class which subclass from QWidget
And this is my header file
#ifndef GRAPHMATRIX_H
#define GRAPHMATRIX_H
#include "treemodel.h"
#include <QWidget>
#include <Qt/qtableview.h>
class GraphMatrix : public QWidget
{
Q_OBJECT
public:
TreeModel& getModel();
GraphMatrix(QWidget* parent = 0);
void addTop(QString name);
void cutComponent(GraphMatrix* component, QVector<int> columns);
private:
TreeModel model;
QTableView* view;
public slots:
void changeValue(const QModelIndex& index);
};
#endif // GRAPHMATRIX_H
And I am getting this error
error C2248: 'QWidget::QWidget' : cannot access private member declared in class 'QWidget'
Can anyone help me?
Updated to add: I find answer, problem is in QList I must write QList. because QList is using copy constructor. Thank you for giving time for my problem
It looks like you are trying to call the default constructor of QWidget which is private. Instead, your constructor needs to call the public constructor of QWidget as follows:
GraphMatrix::GraphMatrix(QWidget* parent) : QWidget(parent) {}
I find answer, problem is in QList I must write QList. because QList is using copy constructor. Thank you for giving time for my problem

Resources