当您以编程方式添加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);
...
}
有没有更好的方法来做到这一点,我错过了?
我为新手问题道歉。
答案 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通常只标记一个项及其属性没有改变。