Myślę, że twoje pytanie może zostać zmienione jako: Kiedy muszę jawnie nadać konstruktorowi widżetów rodzic? Odpowiedź brzmi:
Zawsze, gdy widget jest oknem najwyższego poziomu, w którym zamierzasz mieć rodzica. Takie okna nie podlegają zarządzaniu układem, więc nie ma mechanizmu, który ustawiłby dla ciebie tego rodzica. Transientowe okna najwyższego poziomu muszą mieć rodziców, aby były poprawnie umieszczone w stosunku do okna nadrzędnego.
Zawsze, gdy widget dziecka nie podlega zarządzaniu układem.
Widgety podlega zarządzaniu układu są wychowywane po włożeniu w układzie:
int main(int argc, char ** argv) {
QApplication app(argc, argv);
QWidget window;
QVBoxLayout layout(&window);
QLabel label("Hello");
QPushButton button("Goodbye");
layout.addWidget(&label);
layout.addWidget(&button);
QObject::connect(&button, &QPushButton::clicked, [&app]{ app.quit(); });
window.show();
return app.exec();
}
Wreszcie, nie wszystkie widżety lub QObject
s muszą być wyraźnie tworzone na stercie. Ponieważ wszystkie klasy QObject
-pochodne w Qt (i wiele innych klas też!) używaj idiomu PIMPL, gdy przydzielasz je pojedynczo na stercie, tak naprawdę robisz przydziałdwa razy. Najpierw przydziel instancję klasy - czasami instancja jest tak mała jak wskaźnik lub dwa - a następnie konstruktor klasy przydziela swój PIMPL. Jawne przydzielanie sterty to przypadek przedwczesnej pesymizacji.
Aby uniknąć tego pessimization, twój Widget
powinien wyglądać następująco:
class Widget : public QWidget {
Q_OBJECT
QHBoxLayout m_layout;
QPushButton m_yesButton, m_noButton, m_cancelButton;
public:
Widget(QWidget * parent = 0);
};
Widget::Widget(QWidget * parent) :
QWidget(parent),
m_layout(this),
m_yesButton("&Yes"),
m_noButton("&No"),
m_cancelButton("&Cancel")
{
m_layout.addWidget(&m_yesButton);
m_layout.addWidget(&m_noButton);
m_layout.addWidget(&m_cancelButton);
}
jeśli chce korzystać the PIMPL idiom, można to zrobić, too:
// Widget.h - Interface
class WidgetPrivate;
class Widget : public QWidget {
{
Q_OBJECT
Q_DECLARE_PRIVATE(Widget)
QScopedPointer<WidgetPrivate> const d_ptr;
public:
Widget(QWidget * parent = 0);
~Widget();
};
// Widget.cpp - Implementation
class WidgetPrivate {
Q_DISABLE_COPY(WidgetPrivate)
Q_DECLARE_PUBLIC(Widget)
Widget * const q_ptr;
QHBoxLayout layout;
QPushButton yesButton, noButton, cancelButton;
public:
WidgetPrivate(Widget * q);
};
WidgetPrivate::WidgetPrivate(Widget * q) {
q_ptr(q),
layout(q),
yesButton("&Yes"),
noButton("&No"),
cancelButton("&Cancel")
{
layout.addWidget(&yesButton);
layout.addWidget(&noButton);
layout.addWidget(&cancelButton);
}
Widget::Widget(QWidget * parent) :
QWidget(parent),
d_ptr(new WidgetPrivate(this))
{}
Widget::~Widget() {}
// necessary, since WidgetPrivate is unknown to the interface!
Oczywiście, powinno być przy użyciu QDialogButtonBox
zamiast tego wszystkiego :)
Czy zauważyłeś, że 'QWidget' pochodzi od' QObject'? – cmannett85
Tak, oczywiście, że tak. Ale nie mogę naprawdę zrozumieć, jaki jest sens tego rodzicielskiego związku. –