什么是初始化QWidgets的合适位置?

时间:2013-09-25 04:28:26

标签: qt memory-leaks initializer-list

当您以编程方式添加QWidgets时,初始化QWidgets的最佳方式(地点)是什么?

我可以想办法:

1)在定义文件中创建实例,然后在初始化列表中初始化它们。这似乎是正确的方法,但是你需要添加到窗口的QWidgets越来越松散。

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

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

2)来自C#我倾向于喜欢这个,但它似乎会产生内存泄漏......

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

有没有更好的方法来做到这一点,我错过了?

我为新手问题道歉。

3 个答案:

答案 0 :(得分:3)

Qt使用自己的系统删除父子QObject派生类。删除对象时,也会删除所有子项。

使用第一个代码,你有2个析构(在SomeWindow的析构函数和QObject系统中),那么这个代码是非法的(只有Qt;使用C ++标准代码,这很好)

使用第二个代码,标签被QObject系统删除,您没有内存泄漏。无需将指针保持在对象上。

@Jairo

在构造函数中设置parent不是将子项添加到对象的唯一方法。特别是,这里,QLayout :: addWidget reparent objets(如果布局是对象的正确子对象)

@msgmaxim

小心,布局不能是构造函数中的局部变量

答案 1 :(得分:1)

有两种方法可以初始化新的小部件。

首先,您将标签作为对象。所以当SomeWindow被销毁时,它们也会被自动销毁。请记住,如果您有指向窗口小部件而不是对象的指针,则需要(并且可以)将标签删除到对话框的析构函数中。

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

第二种情况会有内存泄漏,因为你无法将小部件删除到析构函数中。但是,如果为标签定义父级,则父级也将被删除时将删除它们。看看QWidget documentation

  

如果parent为0,则新窗口小部件将成为窗口。如果parent是另一个小部件,则此小部件将成为父级内的子窗口。删除其父窗口时,将删除新窗口小部件。

此外,只要对象构造函数要求您提供父QWidget或QObject,您就可以认为Qt将在删除父对象时删除该对象。

我也是一名新人,但我希望这对你有帮助。

答案 2 :(得分:1)

在标题中指向窗口小部件而不是实际对象的优点是,您不需要包含窗口小部件的所有标头,而只需向前声明它们。这会增加编译时间,这在大型项目中可能非常明显。

此外,如果您有一个对话框并且只是添加了许多小部件,例如QLabel,您可以通过在实现中执行此操作来使代码更整洁: -

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

如前所述,Qt的父系统将在删除父级时清理小部件。

当然,如果你想更改一个属性,比如文本,你需要从布局的子节点中找到小部件,但是正如其名称所暗示的那样,QLabel通常只标记一个项及其属性没有改变。