使用派生 Qt 小部件时的父问题 (?) class
Parent issue (?) while using derived Qt widget class
下面是我能做的最小的例子来展示问题。
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
QGroupBox *gb = new QGroupBox;
// MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
上面的代码产生了上图,它只是一个组合框和一个垂直布局的按钮。
如果我用 MyGroupBox
替换 QGropBox
那么它就不会再显示了。下面的代码生成下面的图像。
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
// QGroupBox *gb = new QGroupBox;
MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
其中mygroupbox.h
(.cpp文件中构造函数体为空):
#include <QWidget>
class MyGroupBox : public QWidget
{
Q_OBJECT
public:
explicit MyGroupBox(QWidget *parent = 0);
signals:
public slots:
};
为什么组框没有显示在那里?如何让它出现?
这就是它没有出现的原因:
class MyGroupBox : public QWidget
你的 "group box" 基本上只是一个 QWidget
。而是从 QGroupBox
继承。
顺便说一句,一个最小的例子可能如下所示。没有一个 declaration/statement/expression 可以删除。该按钮有助于可视化问题,因此应该保留它。失败触发变量的使用突出显示了触发失败的确切条件:代码 self-documents,您几乎不需要叙述来解释它。问题可以像下面的测试用例和一句话"Why is the group box's border not visible when fail
is true?"一样简洁。最有可能的是,如果您完全遵循最小化,您自己就会意识到问题所在 - 它变得相当明显。在另一个文件中声明 MyGroupBox
时就不是这样了!
将所有内容放入单个 main.cpp
文件的技术对于发现问题 至关重要 :所有代码在物理上彼此相邻,因此更容易发现错误!当您最小化时,通常首先要做的是单独的文件:将它们全部塞进一个文件,然后毫不留情地完全删除重现问题时不需要的所有内容。
#include <QtWidgets>
struct MyGroupBox : public QWidget {};
int main(int argc, char ** argv) {
bool fail = true;
QApplication app{argc, argv};
QWidget widget;
QVBoxLayout layout{&widget};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button;
layout.addWidget(fail ? static_cast<QWidget*>(&myGroupBox) : &groupBox);
layout.addWidget(&button);
widget.show();
return app.exec();
}
这种简洁的风格不仅适用于琐碎的测试用例。在您的实际代码中,Widget
的 header 和实现可能如下所示:
// Widget.h
#include <QtWidgets>
#include "MyGroupBox.h"
class Widget : public QWidget {
Q_OBJECT
QVBoxLayout layout{this};
MyGroupBox groupBox;
QPushButton button{tr("Click Me!")};
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h"
Widget::Widget(QWidget * parent) :
QWidget{parent} {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
如果您坚持要从实现细节中屏蔽接口,请不要使用指向小部件等的指针,请使用 PIMPL。
// Widget.h
#include <QWidget>
class WidgetPrivate;
class Widget : public QWidget {
Q_OBJECT
Q_DECLARE_PRIVATE(Widget)
QScopedPointer<WidgetPrivate> const d_ptr;
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h" // should always come first!
#include "MyGroupBox.h"
class WidgetPrivate {
Q_DECLARE_PUBLIC(Widget)
Widget * const q_ptr;
public:
QVBoxLayout layout{q_func()};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button{"Click Me!"};
WidgetPrivate(Widget * q) : q_ptr(q) {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
};
Widget::Widget(QWidget * parent) :
QWidget{parent}, d_ptr{new WidgetPrivate{this}}
{}
下面是我能做的最小的例子来展示问题。
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
QGroupBox *gb = new QGroupBox;
// MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
上面的代码产生了上图,它只是一个组合框和一个垂直布局的按钮。
如果我用 MyGroupBox
替换 QGropBox
那么它就不会再显示了。下面的代码生成下面的图像。
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vLayout = new QVBoxLayout(this);
// QGroupBox *gb = new QGroupBox;
MyGroupBox *gb = new MyGroupBox;
vLayout->addWidget(gb);
QPushButton *btB = new QPushButton;
vLayout->addWidget(btB);
}
其中mygroupbox.h
(.cpp文件中构造函数体为空):
#include <QWidget>
class MyGroupBox : public QWidget
{
Q_OBJECT
public:
explicit MyGroupBox(QWidget *parent = 0);
signals:
public slots:
};
为什么组框没有显示在那里?如何让它出现?
这就是它没有出现的原因:
class MyGroupBox : public QWidget
你的 "group box" 基本上只是一个 QWidget
。而是从 QGroupBox
继承。
顺便说一句,一个最小的例子可能如下所示。没有一个 declaration/statement/expression 可以删除。该按钮有助于可视化问题,因此应该保留它。失败触发变量的使用突出显示了触发失败的确切条件:代码 self-documents,您几乎不需要叙述来解释它。问题可以像下面的测试用例和一句话"Why is the group box's border not visible when fail
is true?"一样简洁。最有可能的是,如果您完全遵循最小化,您自己就会意识到问题所在 - 它变得相当明显。在另一个文件中声明 MyGroupBox
时就不是这样了!
将所有内容放入单个 main.cpp
文件的技术对于发现问题 至关重要 :所有代码在物理上彼此相邻,因此更容易发现错误!当您最小化时,通常首先要做的是单独的文件:将它们全部塞进一个文件,然后毫不留情地完全删除重现问题时不需要的所有内容。
#include <QtWidgets>
struct MyGroupBox : public QWidget {};
int main(int argc, char ** argv) {
bool fail = true;
QApplication app{argc, argv};
QWidget widget;
QVBoxLayout layout{&widget};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button;
layout.addWidget(fail ? static_cast<QWidget*>(&myGroupBox) : &groupBox);
layout.addWidget(&button);
widget.show();
return app.exec();
}
这种简洁的风格不仅适用于琐碎的测试用例。在您的实际代码中,Widget
的 header 和实现可能如下所示:
// Widget.h
#include <QtWidgets>
#include "MyGroupBox.h"
class Widget : public QWidget {
Q_OBJECT
QVBoxLayout layout{this};
MyGroupBox groupBox;
QPushButton button{tr("Click Me!")};
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h"
Widget::Widget(QWidget * parent) :
QWidget{parent} {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
如果您坚持要从实现细节中屏蔽接口,请不要使用指向小部件等的指针,请使用 PIMPL。
// Widget.h
#include <QWidget>
class WidgetPrivate;
class Widget : public QWidget {
Q_OBJECT
Q_DECLARE_PRIVATE(Widget)
QScopedPointer<WidgetPrivate> const d_ptr;
public:
explicit Widget(QWidget * parent = nullptr);
};
// Widget.cpp
#include "Widget.h" // should always come first!
#include "MyGroupBox.h"
class WidgetPrivate {
Q_DECLARE_PUBLIC(Widget)
Widget * const q_ptr;
public:
QVBoxLayout layout{q_func()};
QGroupBox groupBox;
MyGroupBox myGroupBox;
QPushButton button{"Click Me!"};
WidgetPrivate(Widget * q) : q_ptr(q) {
layout.addWidget(&groupBox);
layout.addWidget(&button);
}
};
Widget::Widget(QWidget * parent) :
QWidget{parent}, d_ptr{new WidgetPrivate{this}}
{}