I'm still learning Qt, I did a little project in Qt, i create a simple ui using qt ui designer, and using QGraphicsView to display a image loaded by QFileDialog, but when I added loaded image file to QgraphicsScene, the image is not displayed in the graphicview. The graphicView stay blank, please help me, thanks !
Project2::Project2(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui = new Ui::Project2Class;
ui->setupUi(this);
this->scene = new QGraphicsScene;
this->scene->setSceneRect(0, 0, 649, 459);
connect(ui->mapLoaderButton, SIGNAL(clicked()), this, SLOT(GetfilePath()));
ui->graphicsView->setScene(this->scene);
}
void Project2::GetfilePath()
{
QString filePath = QFileDialog::getOpenFileName(this, tr("Select file"), "", tr("Files (*.jpg*)"));
if (filePath.isNull() == false)
{
QImage image(filePath);
QSize size = image.size();
ui->graphicsView->scene()->addItem(&QGraphicsPixmapItem(QPixmap::fromImage(image)));
ui->graphicsView->scene()->update();
ui->graphicsView->viewport()->update();
}}
QGraphicsScene, and most of Qt, takes ownership of the variable. The variable should be dynamically allocated.
Variables created on the stack won't work, because their lifetimes are too short and the QObject will later try and delete them.
You need to create your QGraphicsPixmapItem with 'new'.
ui->graphicsView->scene()->addItem(new QGraphicsPixmapItem(QPixmap::fromImage(image)));
Everything that inherits from QObject can own (and be owned by) other QObject classes. When a QObject is destroyed, it calls 'delete' on all its children. QObject classes want to 'own' their children. By 'own' I mean control the lifetimes of.
In your case, you were creating the QObject (QGraphicsPixmapItem) on the stack. It's lifetime is then controlled by the stack (but the QObject thinks it's controlling it), and the stack will delete it by the time it reaches the semi-colon of that 'addItem()' function-call.
As a general C++ rule-of-thumb, if a function is asking for a pointer, don't give it a temporary (unnamed) object.
As a general Qt rule-of-thumb, if a function is asking for a pointer, don't even given it a named local-variable - most want a dynamically allocated variable, so look the function up on the documentation and see if it mentions 'taking ownership'. If so, 'new' it and let Qt later 'delete' it.
Related
Shall I delete QObject pointers after using them in Qt 5.7.0?
For example, I have got the code:
std::string login;
std::string password;
if (serviceId == 11) {
QObject* loginField = this->parent()->findChild<QObject*>("wifiLogintxt1");
QObject* passwordField = this->parent()->findChild<QObject*>("wifiPasswordtxt1");
login = loginField->property("text").toString().toStdString();
password = passwordField->property("text").toString().toStdString();
} else {
QObject* loginField = this->parent()->findChild<QObject*>("inputField1");
login = loginField->property("text").toString().toStdString();
}
Will the code lead to a memory leak, because we don't delete QObject pointers?
No, You shouldn't delete these objects, they are managed by their parent QObjects, see QObject trees and ownership:
When using findChild, you are getting a pointer to the same object managed by this parent.
So, loginField, passwordField are deleted when their parent widget is deleted (this instance in your case). If you delete them, they will disappear from the GUI. You have to keep them until the parent widget decides they are no longer needed (that is the time when it is destructed):
You can also delete child objects yourself, and they will remove themselves from their parents. For example, when the user removes a toolbar it may lead to the application deleting one of its QToolBar objects, in which case the tool bar's QMainWindow parent would detect the change and reconfigure its screen space accordingly.
I am new with Qt and i am very confused about how widgets are deleted. I was reading a video and i wanted to show up a QProgressbar while the video frames are being read and then remove this QProgressbar when the video is loaded.
I have done it with 2 different ways:
Using Pointers
QWidget* wd = new QWidget();
QProgressBar* pB = new QProgressBar(wd);
QLabel* label = new QLabel(wd);
//setting geometry and updating the label and progressbar
wd->deleteLater();
wd->hide();
this code is written inside a class and i was assuming when the destructor of this class is called, the widget will be deleted with all of it's children but that didn't happen and everytime i run this function again a new widget is created without hiding or deleting the previous one (NOTE: i have tried to delete the label and progressbar from the widget assuming that they will disappear from inside the widget but this didn't happen "delete(pB);")
Using Objects
QWidget wd;
QProgressBar pB(&wd);
QLabel label(wd);
//setting geometry and updating the label and progressbar
wd.deleteLater();
wd.hide();
When i have run the same code but using objects instead of pointers , it has run exactly as i have wanted and everytime i run the function, the old widget is destroyed and a new one is created.
NOTE: -Also when i close the main window, in case of pointers, the widget wd still exists and the program doesn't terminate until i close them manually
- In case of Objects, when i close the main window everything is closed and the program is terminated correctly.
I need someone to explain me why is this happening and how if i am having a vector of pointers to widgets to delete all pointers inside that vector without any memory leakage
In typical C++ the rule would be "write one delete for every new". An even more advanced rule would be "probably don't write new or delete and bury that in the RIAA pattern instead". Qt changes the rule in this regard because it introduces its own memory management paradigm. It's based on parent/child relationships. QWidgets that are newed can be given a parentWidget(). When the parentWidget() is destroyed, all of its children will be destroyed. Hence, in Qt it is common practice to allocate objects on the stack with new, give them a parent, and never delete the memory yourself. The rules get more complicated with QLayout and such becomes sometimes Qt objects take ownership of widgets and sometimes they don't.
In your case, you probably don't need the deleteLater call. That posts a message to Qt's internal event loop. The message says, "Delete me when you get a chance!" If you want the class to manage wd just give it a parent of this. Then the whole parent/child tree will get deleted when your class is deleted.
It's all really simple. QObject-derived classes are just like any other C++ class, with one exception: if a QObject has children, it will delete the children in its destructor. Keep in mind that QWidget is-a QObject. If you have an instance allocated usingnew`, you must delete it, or ensure that something (a smart pointer!) does.
Of course, attempting to delete something you didn't dynamically allocate is an error, thus:
If you don't dynamically allocate a QObject, don't deleteLater or delete it.
If you don't dynamically allocate a QObject's children, make sure they are gone before the object gets destructed.
Also, don't hide widgets you're about to destruct. It's pointless.
To manage widget lifetime yourself, you should use smart pointers:
class MyClass {
QScopedPointer<QWidget> m_widget;
public:
MyClass() :
widget{new QWidget};
{
auto wd = m_widget->data();
auto pb = new QProgressBar{wd};
auto label = new QLabel{wd};
}
};
When you destroy MyClass, the scoped pointer's destructor will delete the widget instance, and its QObject::~QObject destructor will delete its children.
Of course, none of this is necessary: you should simply create the objects as direct members of the class:
class MyClass {
// The order of declaration has meaning! Parents must precede children.
QWidget m_widget;
QProgressBar m_bar{&m_widget};
QLabel m_label{&m_widget};
public:
MyClass() {}
};
Normally you'd be using a layout for the child widgets:
class MyClass {
QWidget m_widget;
QVBoxLayout m_layout{&m_widget};
QProgressBar m_bar;
QLabel m_label;
public:
MyClass() {
m_layout.addWidget(&m_bar);
m_layout.addWidget(&m_label);
}
};
When you add widgets to the layout, it reparents them to the widget the layout has been set on.
The compiler-generated destructor looks as below. You can't write such code, since the compiler-generated code will double-destroy the already destroyed objects, but let's pretend you could.
MyClass::~MyClass() {
m_label.~QLabel();
m_bar.~QProgressBar();
m_layout.~QVBoxLayout();
// At this point m_widget has no children and its `~QObject()` destructor
// won't perform any child deletions.
m_widget.~QWidget();
}
I have a button, when it is clicked a new window show with a QLineEdit, and a QLabel on it, my connection between the button and the function works fine, but the new window doesn't show.
void windowManager::addQuestionDialog(){
QWidget window(&parent);
QLineEdit question;
QLabel label;
QVBoxLayout layout;
layout.addWidget(&question);
layout.addWidget(&label);
window.setLayout(&layout);
window.resize(200,200);
window.setWindowTitle(QObject::trUtf8("Kérdés bevitele..."));
window.show();
}
You need to create class tag variables for the new window and the stuff you want to put into it, than create the objects themselves with the new keyword in the function, because if you create all of these simply in a function, than they will created in the stack, and you should know that after a function returns/finishes, the stack to that function is deleted (with your new window and the stuff on it too).
Include the headers for the classes you want to use in your windowManager header file:
#include <QDialog>
#include <QLineEdit>
#include <QLabel>
#include <QVBoxLayout>
Then add the tag variables to the private part:
private:
QDialog *window;
QLineEdit *question;
QLabel *label;
QVBoxLayout *layout;
In your button's click event set the tag variables, and create the UI setup:
void windowManager::addQuestionDialog()
{
window = new QDialog();
question = new QLineEdit();
label = new QLabel();
layout = new QVBoxLayout();
layout->addWidget(question);
layout->addWidget(label);
window->setLayout(layout);
window->resize(200,200);
window->setWindowTitle(QObject::trUtf8("Kérdés bevitele..."));
window->show();
}
Also don't forget that you should use -> instead of . for calling functions here, because these tag variables are pointers. Also that's the reason why you don't need to use the & operator to get their address.
Also keep in mind that you should delete these objects, because C++ doesn't delete these automatically for you. You should delete everything you new. A good place to do this is in the destructor in your windowManager class. Just check if the tag variables are not NULL (if there is an object) before you try to delete them, otherwise errors may occur.
A better solution is to pass a parent pointer as the constructor's parameter, so this way Qt will delete them as they are closed, because if the parent is destroyed, the children will be destroyed too.
As an extra, you don't have to set manually where does the objects are go, because Qt will now it from the hierarchy (in some cases).
In this case your button's click event function would look like this:
void windowManager::addQuestionDialog()
{
window = new QDialog(this);
question = new QLineEdit(window);
label = new QLabel(window);
layout = new QVBoxLayout(window);
//The following two lines are optional, but if you don't add them, the dialog will look different.
layout->addWidget(question);
layout->addWidget(label);
window->resize(200,200);
window->setWindowTitle(QObject::trUtf8("Kérdés bevitele..."));
window->show();
}
You create the window QWidget object on the stack. Therefore, this object will be deleted when the call to the function addQuestionDialog finishes. Change the code to create the new window widget using "new", and arrange it to be deleted after it was closed. Some possible solutions are presented here:
destructors in Qt4
I'm fairly new in QT. Taking below fairly simply explain from qt docs :
class CalculatorForm : public QWidget
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
private:
Ui::CalculatorForm ui;
};
and implementation of constructor
CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent) {
ui.setupUi(this); // <-- Question below
}
Q: I was wondering why do we pass this pointer to setupUi function?, what does it do ?
So that the dialog will have the caller as parent, so that eg when the parent is closed the dialog can be closed automatically. Generally all gui elements have a pointer to their parent.
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
These are auto generated slots which exactly match the naming of the gui elments in QtDesigner. They are only meant to do the direct hookup to those gui elements and so should be dealt with in this class. If these signals were extended to other classes then any change in the gui would require changing a lot of other code which doesn't need to know details of the gui.
In the handler slot for the specific gui element you can then emit another more general signal to the rest of the app.
The only widget that setupUi doesn't create is the widget at the top of the hierarchy in the ui file, and as the Ui::CalculatorForm class instance doesn't know the widget it has to fill, it (this) has to be passed explicitly to the class at some point.
this or any other widget you would pass to it, is used as the parent to all other subwidgets. For example, you could fill a widget without inheritance like this:
QWidget *widget = new QWidget;
Ui::CalculatorForm *ui = new Ui::CalculatorForm;
ui->setupUi(widget);
widget->show();
But really, it would be easier to understand if you read the content of the uic generated file (probably named ui_calculatorform.h).
setupUi creates the instances of widgets (QLabel, QTextEdit and so on). The [user interface compiler] (http://qt-project.org/doc/qt-4.8/uic.html) gets information for you from the .UI form and generates widget-creation code in the generated moc source files.
The manual way of creating widgets without using the Qt Designer or a UI file would be like so:
QWidget* pWidget = new QWidget(this);
I think it is to add the caller widget to the layout of this UI.
This widget will be the toplevel widget.
Martin Beckett answer might be correct as well, as what he described is a common behavior in Qt (cf the 'parent' argument in most of widget's derived class constructor)
Note that you have alternative ways how designer can auto-generate code.
In this case you have a separate 'UI' class for this code which is not QObject so it also is not a QWidget.
Auto generated code needs information about parent widget and to make auto-conections of slots and signals so this is why you have to pass this.
This pater is less intrusive then other pasterns (that is why it is default). You can also try alternative patters (check Qt Creator Designer options), but I recommend you to see what is generated by designer tools in default settings.
I'm wondering how to access parent class in my Qt application.
Lets say my project has following structure:
mainWindow: MainWindow
tabWidget: QTabWidget
tab1: MySubClass1
tab2: MySubClass2
tabWidget: QTabWidget
xtab1: MySubSubClass1
xtab2: MySubSubClass2
It is a little simplified.
What I want to do is to access mainWindows object from one of xtab2 slot functions.
(1) What would be the best method ?
I tried to pass the pointer to mainWindow along the tree but I get runtime errors.
(2) Should I include mainwindow.h in xtab.h file or should I do it in xtab.cpp file ?
Thanks for help :)
If you really need the mainwindow, passing the MainWindow pointer is the best way to do it. A static method has the drawback that it will stop working with more than one mainwindow.
I would suggest to avoid accessing the mainwindow from the contained widgets though and use signals instead. E.g.:
class MainWindow {
public:
explicit MainWindow( QWidget* parent=0 ) {
tab = new TabWidget;
...
MySubSubClass1* ssw1 = new MySubSubClass;
connect( ssw1, SIGNAL(textChanged(QString)), this, SLOT(page1TextChanged(QString));
tab->addWidget( ssw1 );
}
private Q_SLOTS:
void page1TextChanged( const QString& ) {
//do something...
}
};
MySubSubClass1 then emits textChanged(), addresseeChanged() (e.g. in Addressbook), or whatever level of abstraction or detail makes sense on the higher level. That way MySubSubClass is generic and doesn't have to know about MainWindow at all. It can be reused in any other context. If MySubSubClass itself contains other widgets, it can again connect to their signals.
You could create a static method and object inside MainWindow that would return mainwindow object.
Something like this:
private:
static MainWindow* _windowInstance
public:
static MainWindow* windowInstance()
{
return _windowInstance;
}
This seems to be the simples solution in most cases. Now you just have to include mainwindow.h whenever you need to access this object.
And don't forget to initialize _windowInstance in the contructor, like this;
_windowInstance = this;
By parent class, I assume you mean parent widget?
If you want to find the top level widget, QWidget::window() will point you to it. Use dynamic_cast or qobject_cast to turn it into your MainWindow object.
If you want to go up some arbitrary level, use paerntWidget().
There are a variety of different solutions to this problem, the one you chose as the answer is in terms of object orientation and encapsulation one of the worse ones. Some thoughts
Encapsulation: if you find yourself having to provide access accross a large distance in relation (down a long chain of containers or subclasses) you might want to look at the functionality that you are trying to distribute. I might be that it should be encapsulated in a class by itself that can passed around easier than where it is currently located (the main window in your case).
Abstraction: Unless it is actually functionality of QMainWindow that you need to access don't pass a pointer to your MainWindow class, create an interface for the functionality that you need, have your MainWindow implement that interface and pass around and object of the interface type instead of your MainWindow type.
Signals and Slots: As Frank noted, implement the appropriate functionality using Qt's signalling mechanism, this makes the connection between the caller and callee into a dynamic one, again separating it from the actual MainWindow class
QApplication: If you absolutely have to have global information restrict the entry point, you already have one singleton the QApplication object, make it the maintainer of all the other objects that need to be globally accessible, derive your own QApplication class and maintain global references in there. Your QApplication class can then create or destroy the needed global objects.
With more information about what you need to do with the MainWindow instance or what needs to be communicated you will also get better answers
QWidget* parent = this ;
while (parent -> parentWidget()) parent = parent -> parentWidget() ;