您现在的位置是:首页 > 技术文章网站首页技术文章

[Qt]FindChild之找孩子

  • WangYe
  • 2020-09-19 22:36:28
  • 245 次阅读
​在Qt编程过程中,通常会有多个部件嵌套,而大多数部件都有父子依赖关系,但是有些情况下不能直接引用子部件,这时我们可以通过父部件来findChild -“查找孩子”

    在Qt编程过程中,通常会有多个部件嵌套,而大多数部件都有父子依赖关系,但是有些情况下不能直接引用子部件,这时我们可以通过父部件来findChild -“查找孩子”


查找选项

  • 枚举Qt::FindChildOption:

Qt::FindChildOptions是一个QFlags<FindChildOption>类型定义,它存储一个或FindChildOption的组合值。

常量描述
Qt::FindDirectChildrenOnly0x0查找object的直接孩子
Qt::FindChildrenRecursively0x1查找object的所有孩子(递归搜索)

findChild

描述

返回对象中类型可以转换为T,并且名为name的孩子。如果不满足条件,则返回0。默认执行递归搜索,除非指定选FindDirectChildrenOnly。

T QObject::findChild(const QString & name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const1

如果有一个以上的孩子匹配搜索,返回最直接的祖先。如果有几个直系祖先,没有定义哪一个将被返回。这种情况下,应该使用findChildren()。

示例

这个示例,返回parentWidget中一个名为“button1”的QPushButton孩子,即使按钮不是父亲的直接孩子:

QPushButton *button = parentWidget->findChild<QPushButton *>("button1");

这个示例,返回parentWidget中的一个QListWidget孩子:

QListWidget *list = parentWidget->findChild<QListWidget *>();

这个示例,返回parentWidget(它的直接父亲)中一个名为“button1”的QPushButton孩子:

QPushButton *button = parentWidget->findChild<QPushButton *>("button1", Qt::FindDirectChildrenOnly);

这个示例,返回parentWidget(它的直接父亲)中的一个QListWidget孩子:

QListWidget *list = parentWidget->findChild<QListWidget *>(QString(), Qt::FindDirectChildrenOnly);

我们不妨来分析一下!

分析

假如我们有一个主界面,主界面上有一个文本为“Parent”的QGroupBox,“Parent”中包含了两个部件及另外一个文本为“Child”的QGroupBox,“Child”中包含了另外两个部件,它们之间的关系如下:

1600524966653298.png

效果:

image.png

源码:

// 构建部件QGroupBox *parentWidget = new QGroupBox(this);
QGroupBox *subWidget = new QGroupBox(this);

QCheckBox *pCheckBox1 = new QCheckBox(parentWidget);
QCheckBox *pCheckBox2 = new QCheckBox(parentWidget);
QCheckBox *pCheckBox3 = new QCheckBox(subWidget);
QCheckBox *pCheckBox4 = new QCheckBox(subWidget);

//设置标题parentWidget->setTitle("Parent");
subWidget->setTitle("Child");

// 设置文本pCheckBox1->setText("CheckBox1");
pCheckBox2->setText("CheckBox2");
pCheckBox3->setText("CheckBox3");
pCheckBox4->setText("CheckBox4");

// 设置objectNamepCheckBox1->setObjectName("name");
pCheckBox2->setObjectName("name1");
pCheckBox3->setObjectName("name");
pCheckBox4->setObjectName("name2");

// 为subWidget设置布局,这时pCheckBox3、pCheckBox4均为它的孩子QVBoxLayout *pSubLayout = new QVBoxLayout();
pSubLayout->addWidget(pCheckBox3);
pSubLayout->addWidget(pCheckBox4);
pSubLayout->setSpacing(10);
pSubLayout->setContentsMargins(10, 10, 10, 10);
subWidget->setLayout(pSubLayout);

// 为parentWidget设置布局,这时pCheckBox1、pCheckBox2、以及subWidget均为它的孩子。QVBoxLayout *pLayout = new QVBoxLayout();
pLayout->addWidget(pCheckBox1);
pLayout->addWidget(pCheckBox2);
pLayout->addWidget(subWidget);
pLayout->setSpacing(10);
pLayout->setContentsMargins(10, 10, 10, 10);
parentWidget->setLayout(pLayout);

到这里,如果对父子级联关系还有问题,你不妨可以调试一下看看:

qDebug() << parentWidget;qDebug() << checkBox1->parent();
qDebug() << checkBox2->parent();
qDebug() << subWidget->parent();
qDebug() << "******************";
qDebug() << subWidget;qDebug() << checkBox3->parentWidget();
qDebug() << checkBox4->parentWidget();

输出如下:

QGroupBox(0x802778)
QGroupBox(0x802778)
QGroupBox(0x802778)
QGroupBox(0x802778)
******************
QGroupBox(0x802a90)
QGroupBox(0x802a90)
QGroupBox(0x802a90)


这说明什么情况?很显然:

  • checkBox3、checkBox4的直接父亲是subWidget。

  • checkBox1、checkBox2、subWidget的直接父亲是parentWidget。

由此可以确定,parentWidget是checkBox3、checkBox4的爷爷(祖先),O(∩_∩)O~。


可能情况

1. 返回NULL

    不能转换为类型T - 与Qt::FindChildOption取值无关。

QPushButton *button = parentWidget->findChild<QPushButton *>();

2. parentWidget所有子孙部件中包含QGroupBox和QCheckBox,但是并没有QPushButton,所以无论是否递归搜索,均返回NULL。

    可以转换为类型T,但是对应的name不存在 - 与Qt::FindChildOption取值无关。

QCheckBox *checkBox = parentWidget->findChild<QCheckBox *>("Qt");

3. parentWidget上有QCheckBox,但是没有名为“Qt”的,所以无论是否递归搜索,均返回NULL。

    可以转换为类型T,对应的name也存在(非直接孩子) - Qt::FindChildOption取值为Qt::FindDirectChildrenOnly。

QCheckBox *checkBox = parentWidget->findChild<QCheckBox *>("name2", Qt::FindDirectChildrenOnly);

4. parentWidget上有名为“name2”的QCheckBox,但是由于采用了Qt::FindDirectChildrenOnly,只会查找直接孩子,而直接孩子中只有名为“name”和“name1”的QCheckBox,所以返回NULL。

    返回非NULL

硬性条件:

1. 可以转换为类型T。
2. 对应的name存在(如果name为空字符串,此条件可忽略,只需要参考1)。

QCheckBox *checkBox1 = parentWidget->findChild<QCheckBox *>("name1");
QCheckBox *checkBox2 = parentWidget->findChild<QCheckBox *>("name2");

由于递归查找,当发现孩子中存在符合要求的就会终止,由于直接孩子中存在名为“name1”的QCheckBox,所以checkBox1表示文本为“CheckBox2”的QCheckBox;由于子孙孩子中存在名为“name2”的QCheckBox,所以checkBox2表示文本为“CheckBox4”的QCheckBox。

    Qt::FindChildOption取值为Qt::FindDirectChildrenOnly

QCheckBox *checkBox = parentWidget->findChild<QCheckBox *>("name", Qt::FindDirectChildrenOnly);

由于采用了Qt::FindDirectChildrenOnly,只会查找parentWidget的直接孩子,直接孩子中存在名为“name”的QCheckBox,所以返回文本为“CheckBox1”的QCheckBox

注意:

理解直接与非直接孩子的区别与关系(可以想象一下血缘关系)。

name是按照objectName()来查找的,并不是text(),切勿搞错。

文章评论 (0)



Top