2013-09-25 5 views
4

Каков наилучший способ (место) инициализировать QWidgets, когда вы добавляете их программно?Что такое подходящее место для инициализации QWidgets?

я могу думать о том, чтобы сделать это:

1) Создание экземпляров в файле определения, а затем инициализировать их в списке инициализации. Кажется, это правильный путь, но он становится неряшливым, чем больше QWidgets, которое нужно добавить в 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) Исходя из C#, как правило, нравится, но это, кажется, генерировать утечку памяти ...

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

Есть ли лучший способ сделать это, что я не хватает?

Приносим извинения за новички вопрос.

+1

Что заставляет вас думать, что в № 2 есть утечка памяти? – thuga

+0

Правильный подход - второй. Это обсуждалось много. Например здесь: http://stackoverflow.com/questions/18984925/c-why-do-i-create-these-widgets-on-the-heap. – vahancho

ответ

3

Qt использует свою собственную систему для удаления родительских дочерних классов QObject. Когда вы удаляете объект, все дети также удаляются.

С первым кодом, у вас есть 2 разрушений (в деструкторе SomeWindow и с системой QObject), то этот код является незаконным (только с Qt, с C++ стандартного кода, это хорошо)

Со вторым кодом , метки удаляются системой QObject, у вас нет утечки памяти. Нет необходимости держать указатель на объектах.

@Jairo

Установка родительского в конструкторе не единственный способ добавить детей к объектам.В частности, здесь, QLayout :: addWidget OBJETS изменит родителя (если макет правильно ребенок объекта)

@msgmaxim

Будьте осторожны, макет не должен быть локальной переменной в конструкторе

1

Два способа хороши для инициализации нового виджета.

В первом случае у вас есть ярлыки в качестве объектов. Поэтому, когда SomeWindow будет уничтожен, они также будут автоматически уничтожены. Помните, если у вас есть указатель на виджеты вместо объектов, вам понадобится (и может) удалить метки в деструктор диалога.

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

И второй случай - утечка памяти, потому что у вас нет способа удалить виджет в деструктор. Но если вы определяете родительский элемент для меток, они будут удаляться, когда родитель также будет удален. Взгляните на QWidget documentation.

Если parent равен 0, новый виджет становится окном. Если родителем является другой виджет, этот виджет становится дочерним окном внутри родителя. Новый виджет удаляется, когда его родитель удален.

Кроме того, в любое время, когда конструктор объектов запрашивает родительский QWidget или QObject, вы можете думать, что Qt удалит объект, когда родитель будет удален.

Я тоже новичок, но я надеюсь, что это поможет вам.

+1

Хотелось бы отметить, что при добавлении виджетов в макет они будут перенаправлены на родительский виджет макета. См. [This] (https://qt.gitorious.org/qt/qt/source/57756e72adf2081137b97f0e689dd16c770d10b1:src/gui/kernel/qlayout.cpp#L318) и [это] (https://qt.gitorious.org/ кварты/кварты/источник/57756e72adf2081137b97f0e689dd16c770d10b1: SRC/GUI/ядро ​​/ qlayout.cpp # l989). [То же самое происходит, когда вы устанавливаете макет для своего виджета] (https://qt.gitorious.org/qt/qt/source/529b30b96435491fc6994515862f44d24efc754f:src/gui/kernel/qwidget.cpp#L8890). – thuga

+1

И вы должны заметить, что в первом случае 'label1;' не является указателем. Поэтому 'delete label1' не будет работать. В любом случае он будет удален автоматически, поэтому удаление его в деструкторе просто вызовет проблемы. – thuga

+0

@thuga Спасибо за указание на макеты. _label1; не является указателем_ ... ups. Сейчас я отредактирую ответ. – Jairo

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, как следует из его названия, просто накладывает элемент и его свойства не изменяются.

Смежные вопросы