LINUX.ORG.RU

findChild() - почему оно срабатывает без указателя на parent? Забыл за давностью лет.

 


0

1

В Qt у каждого наследника QObject есть имя, которое устанавливается через setObjectName(). И есть метод findChild(), который способен искать объект по имени и типу (причем рекурсивно).

Поиск происходит примерно так:

MyObject *findObj=StartObject->findChild<MyObject *>("myObject");

Я написал краткий пример, в котором проверяю, как работает поиск: http://rghost.ru/7Pqg5XrvQ

Поигравшись с примером, я написал вот такую статью-объяснение, в которой вроде все логично написано: http://webhamster.ru/mytetrashare/index/mtb0/1440832556nzl24l7k21

В частности, в статье я вывел следующее правило:

Поиск будет работать только в том случае, если в объекте класса, унаследованного от QObject, будет задан parent-объект.

и подтвердил это правило на примере:

// При такой инициализации поиск работает
First *first=new First(pMainWindow);
first->setObjectName("first");

Second *second=new Second(pMainWindow);
second->setObjectName("second");


// При такой инициализации поиск не работает
First *first=new First();
first->setObjectName("first");

Second *second=new Second();
second->setObjectName("second");

Однако, у меня есть проект вот с такими исходниками:

https://github.com/xintrea/mytetra_dev/commit/9412b044c108fe6cbe03e39c5c2a842...

(последний рабочий коммит - 9412b044c108fe6cbe03e39c5c2a8421a530fadb)

И в этом проекте волшебным образом работает поиск через findChild(), несмотря на то, что объекты не имеют родителей.

Смотрим файл src/views/mainWindow/MainWindow.cpp, метод setupUI(). В нем создаются объекты без родителя, и нигде больше родитель для этих объектов не задается. Но несмотря на это, поиск таких объектов работает:

find_object<TreeScreen>("treeScreen")->saveKnowTree();

Реализация find_object() использует findChild(), и расположена в main.h (темплейт).

Вопрос. Почему в проекте поиск работает несмотря на то, что parent не задан? А почему в примере поиск не работает, если parent не задан?

★★★★★

Последнее исправление: Xintrea (всего исправлений: 2)

Потому что когда виджет помещается в лейаут, то лейаут обычно становится его новым родителем. Иногда нет, это указывается в документации.

Поэтому, когда ты делаешь

void MainWindow::assembly(void)
{
 // ...
 hSplitter->addWidget(treeScreen); // Дерево веток

 // ...
 findSplitter->addWidget(hSplitter);
 // ... 

 setCentralWidget(findSplitter);
}
то treeScreen — это уже дочерний объект MainWindow.

ilammy ★★★
()
Ответ на: комментарий от ilammy

Похоже на то, видимо я об этом как раз и забыл.

Но помнится мне, что была какая-то трабла, когда в MainWindow создаешь объект, и при создании задаешь ему в качестве parent ссылку this. А потом засовываешь объект в layout, и происходила какая-то нехорошая вещь.

Вот не помню, в чем была проблема. То ли заданный parent не менялся, то ли наоборот менялся на layout, и из-за этого какие-то глюки были.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от ilammy

Только родителем становится не лэйаут, а виджет, которому принадлежит лэйаут.

fluorite ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.