Question

What is the best way (place) to initialize QWidgets, when you add them programmatically?

I can think of ways to do it:

1) Create instances in the definition file and then initialize them in the initializer list. This seems to be the right way, but it becomes kind of sloppy the more QWidgets you need to add to the Window.

class SomeWindow : QDialog{
...
private:
  QLabel label1;
  QLabel label2;
...
}

SomeWindow::SomeWindow(...) : QDialog(...),
 label('label1 text'), label('label2 text')
{
...
  layout.addWidget(&label1);
  layout.addWidget(&label2);
...
}

2) Coming from C# I tend to like this, but it seem to generate memory leak...

SomeWindow::SomeWindow(...) : QDialog(...)
{
  QLabel* label1 = new QLabel('label1 text');
  QLabel* label2 = new QLabel('label2 text');
...
  layout.addWidget(label1);
  layout.addWidget(label2);
...
}

Is there a better way to do this that I'm missing?

I appologize for the newbie question.

Was it helpful?

Solution

Qt use his own system to delete parent-children QObject derived classes. When you delete object, all children are deleted too.

With the first code, you have 2 destructions (in destructor of SomeWindow and with QObject system), then this code is illegal (only with Qt ; with C++ standard code, it's good)

With the second code, labels are delete by QObject system, you don't have memory leak. No need to keep pointer on objects.

@Jairo

Setting parent in constructor is not the only way to add children to objects. In particular, here, QLayout::addWidget reparent objets (if layout is correctly child of object)

@msgmaxim

Be carefull, layout must not be local variable in constructor

OTHER TIPS

An advantage to having pointers to widgets in the headers, rather than the actual objects, is that you don't need to include all the headers for the widgets, but just forward declare them. This increases compilation time, which can be considerably noticeable in large projects.

In addition, if you have a dialog and are just adding a lot of widgets, such as a QLabel, you can make the code neater by doing this in the implementation: -

layout.addWidget(new QLabel('label1 text'));
layout.addWidget(new QLabel('label2 text'));
layout.addWidget(new QLabel('label3 text'));
layout.addWidget(new QLabel('label4 text'));

As has been mentioned, Qt's parent system will take care of cleaning up the widgets when their parent is deleted.

Of-course, if you want to change a property, such as the text, you'd then need to find the widget from the layout's children, but often QLabel, as its name implies, just labels an item and its properties aren't changed.

Two ways are good in order to initialize a new widget.

First case you have labels as objects. So when SomeWindow is destroyed, they will be destroyed automatically too. Remember, if you have pointer to widgets instead objects, you will need (and can) to delete the labels into destructor of dialog.

SomeWindow::~SomeWindow()
{
    delete label1;
    label2.deleteLater(); // A safer way to delete a widget. Thread-safe.
}

And second case there will be a memory leak because you have no way to delete the widget into destructor. But if you define a parent for labels, they will be delete when parent is delete too. Take a look to QWidget documentation.

If parent is 0, the new widget becomes a window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted.

Moreover, anytime a object constructor ask you for a parent QWidget or QObject, you can think that Qt will delete the object when the parent is deleted.

I am a newbey as well, but I hope this help you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top