【问题标题】:What is an appropriate place to initialize QWidgets?什么是初始化 QWidgets 的合适位置?
【发布时间】:2013-09-25 04:28:26
【问题描述】:

当您以编程方式添加 QWidget 时,初始化 QWidget 的最佳方式(位置)是什么?

我能想到办法:

1) 在定义文件中创建实例,然后在初始化列表中初始化它们。这似乎是正确的方法,但是您需要添加到窗口中的 QWidget 越多,它就会变得有点草率。

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);
...
}

有没有我想念的更好的方法来做到这一点?

我为新手问题道歉。

【问题讨论】:

标签: qt memory-leaks initializer-list


【解决方案1】:

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

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

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

@Jairo

在构造函数中设置父级并不是将子级添加到对象的唯一方法。特别是,在这里,QLayout::addWidget 重新父对象(如果布局正确地是对象的子对象)

@msgmaxim

注意,布局不能是构造函数中的局部变量

【讨论】:

    【解决方案2】:

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

    此外,如果您有一个对话框并且只是添加了很多小部件,例如 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,顾名思义,只是标记一个项目及其属性没有改变。

    【讨论】:

      【解决方案3】:

      有两种方法可以很好地初始化一个新的小部件。

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

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

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

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

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

      我也是新手,希望对你有所帮助。

      【讨论】:

      • 我想指出,当您将小部件添加到布局时,它们将被重新设置为布局的父小部件。请参阅 thisthisSame thing happens when you set a layout to your widget.
      • 您应该注意,在第一种情况下,label1; 不是指针。所以delete label1 将不起作用。无论如何它都会被自动删除,所以在析构函数中删除它只会导致问题。
      • @thuga 感谢您指出布局。 标签1;不是指针 ... ups。我现在要编辑答案。
      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-28
      相关资源
      最近更新 更多