几乎每个 QtWidgets 类都可以有 parent。而且通常在对象初始化时设置 parent 是可选的。例如,如果我创建一个继承QWidget
类的类,我会在构造函数上执行以下操作:
Widget::Widget(QWidget* parent): QWidget(parent) {
hbox = new QHBoxLayout(this);
yes_on = new QPushButton("&Yes");
no_on = new QPushButton("&No", this);
cancel_on = new QPushButton("&Cancel", hbox);
}
我可以设置或不设置 parent。我可以将cancel_on
设置为hbox
的孩子。我也可以将cancel_on
设置为yes_on
的孩子,但我认为这是一件坏事。
而且,真的有必要为我创建的每个基于QWidget
的类设置父类吗?
除了帮助 GUI 对象中的绘制顺序之外,它还有助于内存管理,因此当您销毁 QObject 时,它的所有子对象也会被销毁。有关更多详细信息,请参见http://doc.qt.io/qt-4.8/objecttrees.html。当父对象中的某些内容发生变化时(例如,调整其大小),它可以通知其子对象也更新自己。
为了回答你的问题,你不需要为所有内容设置父级(这就是为什么它是一个可选参数,毕竟),但大多数时候最好正确设置它。
首先,QWidget
是QObject
,QObject
是QObject
树中的节点。子节点由父节点进行内存管理,除非您在父节点有机会这样做之前将其释放。因此,内存管理是小部件或任何其他QObject
具有父级的原因之一。
其次,可见的无父级小部件是总是顶级窗口。相反,不可能有一个无父级的非顶级小部件。当您显示无父级小部件时,它将获得自己的窗口。相反的情况不一定是正确的-可以给子小部件一个Qt::Window
标志,并且它也成为一个顶级窗口。
推论是任何小部件包含在其他小部件有父-否则它将是一个顶级窗口。
我认为你的问题可以改写为:我什么时候需要明确地给小部件构造函数父?
只要小部件是您打算具有父窗口的顶级窗口。此类窗口不受布局管理,因此没有为您设置该父窗口的机制。顶级瞬态对话框需要具有父级,以便它们相对于父窗口正确定位。
每当你有一个子部件不受布局管理。
受布局管理约束的小组件在插入到布局中时具有父级:
int main(int argc, char ** argv) {
QApplication app(argc, argv);
QWidget window;
QVBoxLayout layout(&window);
QLabel label("Hello");
QPushButton on("Goodbye");
layout.addWidget(&label);
layout.addWidget(&on);
QObject::connect(&on, &QPushButton::clicked, [&app]{ app.quit(); });
window.show();
return app.exec();
}
最后,并不是所有的小部件或QObject
都需要在堆上显式创建。由于 Qt 中的所有QObject
-派生类 (以及许多其他类!) 使用 PIMPL 习语,当您在堆上单独分配它们时,您实际上是在进行堆分配两次。首先分配类的实例,然后是 PIpespes 的两个指针
为了避免这种悲观,你的Widget
应该如下所示:
cl 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);
}
如果你想使用the PIMPL idiom,你也可以这样做:
// Widget.h - Intece
cl WidgetPrivate;
cl Widget : public QWidget {
{
Q_OBJECT
Q_DECLARE_PRIVATE(Widget)
QScopedPointer<WidgetPrivate> const d_ptr;
public:
Widget(QWidget * parent = 0);
~Widget();
};
// Widget.cpp - Implementation
cl 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 intece!
当然,您应该使用QDialogButtonBox
而不是所有这些:)
本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处
评论列表(13条)