Zuerst ist ein QWidget
ein QObject
, und QObject
sind Knoten in einem QObject
Baum. Die untergeordneten Knoten werden vom übergeordneten Speicher verwaltet, es sei denn, Sie heben die Zuordnung auf, bevor der übergeordnete Knoten die Möglichkeit dazu hat. Daher ist die Speicherverwaltung ein Grund dafür, dass Widgets oder andere Elemente einen Elternteil haben.
Zweitens sind sichtbare elternlose Widgets immer Top-Level-Windows. Umgekehrt ist es unmöglich, ein Widget ohne Top-Level zu haben, das ohne Eltern ist. Wenn Sie ein Widget ohne Eltern anzeigen, erhält es ein eigenes Fenster. Das Gegenteil ist nicht unbedingt wahr - es ist möglich, einem Kind-Widget ein Qt::Window
-Flag zu geben, und es wird auch ein Top-Level-Fenster.
Die logische Folge ist, dass jede Widget in andere Widgets enthalten ein Elternteil hat - sonst wäre es ein Fenster der obersten Ebene sein. Dieser Parent wird möglicherweise nicht explizit von Ihnen festgelegt, aber trotzdem gesetzt.
Ich denke, dass Ihre Frage wie neu formuliert werden kann: Wann muss ich Widget-Konstruktor explizit Eltern geben? Die Antwort lautet:
Jedes Mal, wenn das Widget ein Top-Level-Fenster, das Sie beabsichtigen, einen Elternteil zu haben. Solche Fenster unterliegen nicht der Layout-Verwaltung, daher gibt es keinen Mechanismus, um dieses übergeordnete Element für Sie festzulegen. Transiente Dialoge auf höchster Ebene müssen Eltern haben, damit sie in Bezug auf das Elternfenster richtig positioniert sind.
Immer wenn Sie ein Kind-Widget haben, das nicht der Layoutverwaltung unterliegt.
Widgets unterliegen Layout-Management werden beim Einfügen in ein Layout parented:
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();
}
schließlich nicht alle Widgets oder QObject
s müssen explizit auf dem Heap angelegt werden. Da alle QObject
-abgeleitete Klassen in Qt (und viele andere Klassen auch!) Verwenden Sie das PIMPL-Idiom, wenn Sie sie einzeln auf dem Heap zuweisen, tun Sie wirklich die Heap-Zuweisung zweimal. Zuerst weisen Sie die Instanz der Klasse zu - manchmal ist die Instanz so klein wie ein oder zwei Zeiger - und dann weist der Konstruktor der Klasse seine PIMPL zu. Die explizite Heap-Zuweisung ist ein Fall von vorzeitiger Pessimierung.
dieses Pessimierung zu vermeiden, Ihre Widget
wie folgt aussehen:
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);
}
Wenn Sie wollte the PIMPL idiom verwenden, können Sie das auch tun:
// 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!
Natürlich sollten Sie sein mit QDialogButtonBox
statt all dem :)
Haben Sie bemerkt, dass 'QWidget' von' QObject' abgeleitet ist? – cmannett85
Ja, natürlich ist es. Aber ich kann nicht wirklich verstehen, was der Sinn dieser Elternbeziehung ist. –