Russian Qt Forum

Qt => Общие вопросы => Тема начата: xintrea от Апрель 16, 2016, 11:35



Название: Как найти через findChild() член класса по QObject-имени?
Отправлено: xintrea от Апрель 16, 2016, 11:35
У меня был класс с множеством объектов-кнопок. Эти объекты создавались динамически, то есть:

Код:
h-файл:

QToolButton *bold;
QToolButton *italic;
QToolButton *underline;

c++ файл:

QToolButton *bold=new QToolButton(this);
bold->setObjectName("editor_tb_bold");

QToolButton *italic=new QToolButton(this);
italic->setObjectName("editor_tb_italic");

QToolButton *underline=new QToolButton(this);
underline->setObjectName("editor_tb_underline");

Мне все твердят, что так делать ненада, нужно просто сделать кнопки членами класса, а не указатели на них. Я так и сделал:

Код:
h-файл:

QToolButton bold;
QToolButton italic;
QToolButton underline;

c++ файл:

bold.setObjectName("editor_tb_bold");

italic.setObjectName("editor_tb_italic");

underline.setObjectName("editor_tb_underline");

Кнопки нужно в рантайме повтыкать на панель инструментов в последовательности, настроенной пользователем. (Точнее, вставлять нужно не только кнопки, но и например выпадающие списки). Вставка происходит по имени вставляемого объекта.

Ранее, когда были указатели, метод вставки в панель инструментов выглядел так:

Код:
void EditorToolBar::insertButtonToToolsLine(QString toolName, QToolBar *line)
{
  if(toolName=="separator")
    line->addSeparator();
  else
  {
    QString name("editor_tb_"+toolName);
    QWidget *tool=this->findChild<QWidget *>(name);
    if(tool!=NULL)
    {
      tool->setVisible(true);
      line->addWidget(tool); // Инструмент добавляется на панель инструментов
 ...

Теперь, когда членами класса являются не указатели на виджеты, а сами виджеты, я не могу понять, как воспользоваться методом findChild().

В документации на этот метод ничего не сказано о том, что он не может работать с обычными объектами, а не с указателями:

Цитировать
T QObject::findChild(const QString & name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const

Returns the child of this object that can be cast into type T and that is called name, or 0 if there is no such object. Omitting the name argument causes all object names to be matched. The search is performed recursively, unless options specifies the option FindDirectChildrenOnly.

If there is more than one child matching the search, the most direct ancestor is returned. If there are several direct ancestors, it is undefined which one will be returned. In that case, findChildren() should be used.

Я пробовал получить указатель на член класса так:

Код:
QWidget *tool=this->findChild<QWidget *>(name);
QWidget *tool=&( qobject_cast<QWidget>( this->findChild<QWidget>(name) ) );
QWidget *tool=&( qobject_cast<QWidget>( &(this->findChild<QObject>(name)) ) );
QWidget *tool=qobject_cast<QWidget *>( &(this->findChild<QObject>(name)) );

Как я только не пробовал - ничего не получается.

Вопрос. Как заполучить указатель на член класса по QObject-имени объекта?


Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: Igors от Апрель 16, 2016, 11:59
Мне все твердят, что так делать ненада, нужно просто сделать кнопки членами класса, а не указатели на них. Я так и сделал:
Наоборот, совершенно (принципиально) неверно делать кнопки членами. Так Вы нарываетесь на проблемы с Qt parent-chilld, и без нужды будете ломать голову какое удаление состоится первым. Если хотите упорствовать, то обеспечьте родителя
Код
C++ (Qt)
EditorToolBar::EditorToolBar( void ) :
bold(this),
italic(this),
underline(this)
{
...
}
 
Без этого кнопари будут созданы как самостоятельные окна (parent = 0) и, конечно findChild их не найдет. И имена уж слишком ходовые, поменяйте напр на btnBold и.т.п.




Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: PimenS от Апрель 16, 2016, 12:05
У меня был класс с множеством объектов-кнопок. Эти объекты создавались динамически, то есть:

Код:
h-файл:

QToolButton *bold;
QToolButton *italic;
QToolButton *underline;

c++ файл:

QToolButton *bold=new QToolButton(this);
bold->setObjectName("editor_tb_bold");

QToolButton *italic=new QToolButton(this);
italic->setObjectName("editor_tb_italic");

QToolButton *underline=new QToolButton(this);
underline->setObjectName("editor_tb_underline");

Мне все твердят, что так делать ненада, нужно просто сделать кнопки членами класса, а не указатели на них. Я так и сделал:


Первый вариант самый правильный. И не надо никаких
Цитировать
нужно просто сделать кнопки членами класса, а не указатели на них

Правда не пойму зачем вы объявляете QToolButton, а потом делаете повторное объявление. Я бы сделал так:

Код:
h-файл:

QToolButton *bold;
QToolButton *italic;
QToolButton *underline;

c++ файл:

bold = new QToolButton(this);
bold->setObjectName("editor_tb_bold");

italic = new QToolButton(this);
italic->setObjectName("editor_tb_italic");

underline = new QToolButton(this);
underline->setObjectName("editor_tb_underline");


Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: Old от Апрель 16, 2016, 20:04
Так Вы нарываетесь на проблемы с Qt parent-chilld
О, по-моему уже раз восьмой заходит тема... :)
А расскажите нам пожалуйста о этих пробламах "с Qt parent-chilld".

и без нужды будете ломать голову какое удаление состоится первым.
А для чего ему ломать над этим голову? :)
Когда там все очевидно. :)

2 xintrea. Посмотрите на QAction.


Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: lit-uriy от Апрель 18, 2016, 14:44
Какая-то каша у обоих в головах.

Член класса - это НЕ объект в куче.

Когда используются указатели на кнопки, они могут быть как членами класса, так и не быть ими.
в первом примере у xintrea члены класса (судя по всему ни разу не инициализированный) и есть инициализированные локальные указатели.

А вот тут указатели являются членами класса и корректно инициализированы:
Код
C++ (Qt)
class SettingsDialog : public QDialog
{
QToolButton *bold;
QToolButton *italic;
QToolButton *underline;
}
 
Код
C++ (Qt)
SettingsDialog::SettingsDialog(...)
{
bold=new QToolButton(this); // не обявление новой локальной переменной, а использование ранее объявленного члена класса
bold->setObjectName("editor_tb_bold");
 
italic=new QToolButton(this);  // не обявление новой локальной переменной, а использование ранее объявленного члена класса
italic->setObjectName("editor_tb_italic");
 
underline=new QToolButton(this); // не обявление новой локальной переменной, а использование ранее объявленного члена класса
underline->setObjectName("editor_tb_underline");
}
 


Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: Igors от Апрель 18, 2016, 16:51
Какая-то каша у обоих в головах.

Член класса - это НЕ объект в куче.
А где же он если родитель в куче? Вероятно Вы хотели сказать что для виджета члена класса (не указателя) нельзя звать delete - с этим никто не спорит

А вот тут указатели являются членами класса и корректно инициализированы:
Во всяком случае более "академично" инициализировать члены в списке инициализации конструктора (а не в его теле)


Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: lit-uriy от Апрель 19, 2016, 12:15
да, ошибся. Надо было написать "на стеке".

вторая попытка у xintrea свелась к тому, что создал члены класса на стеке, вместо того, чтобы избавиться от локальных переменных по имени совпадающих с членами класса.


Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: Igors от Апрель 19, 2016, 12:49
А вообще если собрались выдергивать объект по имени - зачем вообще член класса (хоть указатель хоть нет)? Ну и достаем его всякий раз по имени, это по крайней мере принципиально/идейно.


Название: Re: Как найти через findChild() член класса по QObject-имени?
Отправлено: Old от Апрель 19, 2016, 12:51
А вообще если собрались выдергивать объект по имени - зачем вообще член класса (хоть указатель хоть нет)? Ну и достаем его всякий раз по имени, это по крайней мере принципиально/идейно.
Для чего здесь виджеты совсем не понятно. :)
QMap и QAction для этого использовать одно удовольствие.