Russian Qt Forum

Qt => Общие вопросы => Тема начата: tux от Март 04, 2020, 14:35



Название: Qt: преобразованные виджеты
Отправлено: tux от Март 04, 2020, 14:35
Доброго времени суток!
1) Создал свой класс MyClass.
2) Создал форму
3) На форму добавил виджет
4) Преобразовал добавленный виджет в MyClass
5) Задал ему objeсtName в дизайнере, допустим my_widget
Вопрос: могу ли я как то из класса MyClass увидеть этот самый my_widget? Без использования редактора, просто из кода.


Название: Re: Qt: преобразованные виджеты
Отправлено: Авварон от Март 04, 2020, 14:40
Код:
ui->my_widget


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 04, 2020, 14:41
Код:
ui->my_widget
Не. Изнутри класса. К ui родительского объекта ведь так просто не доберёшься...


Название: Re: Qt: преобразованные виджеты
Отправлено: Авварон от Март 04, 2020, 14:51
Код:
this


Название: Re: Qt: преобразованные виджеты
Отправлено: Авварон от Март 04, 2020, 14:53
Нет, серьезно, класс MyClass ничего не знает (и не должен знать) о форме, на которой он будет размещен, ведь он может быть не размещен на форме!

Если очень хочется, то можно подняться через parent() на уровень выше (а там и еще выше), но совершенно неясно зачем - виджет должен общаться через сигнал\слоты с окружающим миром.


Название: Re: Qt: преобразованные виджеты
Отправлено: Igors от Март 04, 2020, 15:03
Вопрос: могу ли я как то из класса MyClass увидеть этот самый my_widget? Без использования редактора, просто из кода.
Строго говоря - нет. Код создается для класса экземпляров которого может быть сколько угодно. Отличить проще всего по имени, напр
Код
C++ (Qt)
void MyClass::DoSometrhing( .. )
{
 if (this->objectName() == "Вася")
  ..
}
 
Хотя это конечно коряво  :)
 


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 04, 2020, 15:07
Допустим, в этом классе MyClass есть объект QSpinBox. И ещё 100500 визуальных компонентов.
Я на родительской форме размещаю десяток простых widget, которые затем преобразовываю в MyClass.
А теперь я хочу в родительском классе сохранить значения этих QSpinBox. Я могу пройтись по всем QSpinBox и сохранить их значения, всё хорошо. Но как их различить друг от друга - objectName то у всех одинаковый.
Если бы я знал objectName "контейнера", то я бы в самом классе сохранял/восстанавливал состояния своих визуальных объектов.


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 04, 2020, 15:08
Вопрос: могу ли я как то из класса MyClass увидеть этот самый my_widget? Без использования редактора, просто из кода.
Строго говоря - нет. Код создается для класса экземпляров которого может быть сколько угодно. Отличить проще всего по имени, напр
Код
C++ (Qt)
void MyClass::DoSometrhing( .. )
{
 if (this->objectName() == "Вася")
  ..
}
 
Хотя это конечно коряво  :)
Проблема только в том, что objectName будет у всех таких объектов одинаковый...


Название: Re: Qt: преобразованные виджеты
Отправлено: Авварон от Март 04, 2020, 15:14
Сделайте методы QByteArray saveState()/void restoreState(const QByteArray &state) в MyClass. В простом случае можно сделать геттер\сеттер для спинбокса.

А потом проходите по всем MyClass (или конкретному):
Код:
for (auto *child : findChildren<MyClass>()) {
    // получили стейт
    auto state = child->saveState();
    // сохраняем куда-то (в мапу сеттингзы или еще куда)
    map[child->objectName()] = state;
}


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 04, 2020, 15:23
Сделайте методы QByteArray saveState()/void restoreState(const QByteArray &state) в MyClass. В простом случае можно сделать геттер\сеттер для спинбокса.

А потом проходите по всем MyClass (или конкретному):
Код:
for (auto *child : findChildren<MyClass>()) {
    // получили стейт
    auto state = child->saveState();
    // сохраняем куда-то (в мапу сеттингзы или еще куда)
    map[child->objectName()] = state;
}
Проблема в подобном решении в том, что я в КАЖДОМ классе, использующем MyClass буду вынужден вызывать эти самые saveState/restoreState. И стОит где-то это забыть и всё...
Хотелось бы как то изнутри MyClass это делать. Один раз написать и забыть. И если бы знать ИЗНУТРИ класса, назначенный ему СНАРУЖИ objectName - было бы просто замечательно.


Название: Re: Qt: преобразованные виджеты
Отправлено: Igors от Март 05, 2020, 08:47
И если бы знать ИЗНУТРИ класса, назначенный ему СНАРУЖИ objectName - было бы просто замечательно.
Так он и назначается "снаружи" (а не в коде класса) - см код создаваемый дызайнером


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 05, 2020, 18:44
Так он и назначается "снаружи" (а не в коде класса) - см код создаваемый дызайнером
Ну так я и спрашиваю, как именно его увидеть изнутри класса? Я и так знаю, что он создается "дызайнером". :)


Название: Re: Qt: преобразованные виджеты
Отправлено: Igors от Март 06, 2020, 11:18
Ну так я и спрашиваю, как именно его увидеть изнутри класса? Я и так знаю, что он создается "дызайнером". :)
Проблема только в том, что objectName будет у всех таких объектов одинаковый...
Нет. "objectName" - обычная пропердь, у экземпляра созданного дызайнером она будет = "Вася", у других пустая строка по умолчанию (или то что им установили)


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 06, 2020, 22:04
Нет. "objectName" - обычная пропердь, у экземпляра созданного дызайнером она будет = "Вася", у других пустая строка по умолчанию (или то что им установили)
Вы можете ведь сами проверить - будет не так. Изнутри класса objectName будет одним, а в редакторе - другим.
Я в начале тоже думал, что они должны быть одинаковыми - однако реальность показывает другое.
P.S. Я, конечно, могу допустить, что в винде всё может быть по-другому. Но меня больше интересуют linux и macos


Название: Re: Qt: преобразованные виджеты
Отправлено: Igors от Март 07, 2020, 14:05
Вы можете ведь сами проверить - будет не так. Изнутри класса objectName будет одним, а в редакторе - другим.
Я в начале тоже думал, что они должны быть одинаковыми - однако реальность показывает другое.
Неясно что и как Вы проверяли. Если напр Вы печатали objectName в конструкторе MyClass, то он будет пустым. Только после того как код дызайнера выполнит setObjectName он станет заданным, и только для этого экземпляра. Если не согласны - запостите проект в zip'е, а иначе нет нужды проверять то что следует из доки класса и общих принципов языка.

P.S. Я, конечно, могу допустить, что в винде всё может быть по-другому. Но меня больше интересуют linux и macos
И не надо так плохо думать о людях - моя платформа OSX


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 07, 2020, 20:28
Не вопрос.
Вот "на коленке" набросал проект. Фактически то, что я описывал в начале темы.
Может быть, я хочу чего-то принципиально невозможного, но я хочу увидеть в консоли "my_widget", а не "MyClass".


Название: Re: Qt: преобразованные виджеты
Отправлено: kambala от Март 08, 2020, 11:09
это невозможно: достаточно просто взглянуть на сгененрированный код в ui_mainwindow.h. Самым простым решением будет вызвать функцию из MyClass::MyClass() по таймеру с нулевой задержкой:
Код
C++ (Qt)
   QTimer::singleShot(0, [this]{
       qDebug() << objectName();
   });


Название: Re: Qt: преобразованные виджеты
Отправлено: Igors от Март 08, 2020, 11:36
Вот он в консоле
Код
C++ (Qt)
#include "mainwindow.h"
 
#include <QApplication>
#include <QDebug>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   MainWindow w;
qDebug() << w.findChild<QWidget *>("MyClass");
qDebug() << w.findChild<QWidget *>("my_widget");
   w.show();
   return a.exec();
}
 
Есть объект с именем "my_widget" (а с именем "MyClass" нет). Ваша печать покажет MyClass потому что
Код
C++ (Qt)
class Ui_MyClass
{
public:
 
   void setupUi(QWidget *MyClass)
   {
       if (MyClass->objectName().isEmpty())
           MyClass->setObjectName(QStringLiteral("MyClass"));
       MyClass->resize(400, 300);
 
       retranslateUi(MyClass);
 
       QMetaObject::connectSlotsByName(MyClass);
   } // setupUi
Дызайнер сначала поставит "MyClass", и только потом, при установке MainWindow, поставит "my_widget". Возможно потому что "MyClass" требуется для connectSlotsByName, ну это личное дело дызайнера.

Все работает "как доктор прописал", увидеть из экземпляра заданное имя можно только после того как оно установлено.


Название: Re: Qt: преобразованные виджеты
Отправлено: tux от Март 08, 2020, 15:17
это невозможно: достаточно просто взглянуть на сгененрированный код в ui_mainwindow.h. Самым простым решением будет вызвать функцию из MyClass::MyClass() по таймеру с нулевой задержкой:
Код
C++ (Qt)
   QTimer::singleShot(0, [this]{
       qDebug() << objectName();
   });
Хитро! Но работает.
Спасибо!