Russian Qt Forum
Сентябрь 22, 2024, 22:30 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Сигналы, слоты, и реализация геттеров.  (Прочитано 7187 раз)
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« : Октябрь 06, 2008, 12:01 »

Здравствуйте!


Вот тут раздумываю над структурой приложения. Есть главное окно, в него понапиханы разные самодельные виджеты. У классов виджетов есть обычные public геттеры и сеттеры.

И вот вопрос. Мне нужно, чтобы виджеты устанавливали и получали значения из других виджетов.


Сеттер. Сеттер я могу реализовать просто в виде слота. Ну например

Код:
public slots:
 void set_url(QString url);

В главном окне связываю нужные виджеты, чтоб сеттер работал

Код:
connect(pageview,SIGNAL(do_urlview_set_url(QString)),urlview,SLOT(set_url(QString));

В виджете (из которого надо вызвать установку значения url), сеттер вызывается так

Код:
emit do_urlview_set_url("http://prog.org.ru");

Вот такой путь организации сеттеров я себе придумал. Не очень по-моему правильный, но как минимум работает. Я бы конечно вообще без сигналов-слотов хотел все сделать, но непонятно как в вышеописаной конфигурации приложения это делать.


Геттер. А вот как сделать геттер, чтоб простым образом получать значение, по-нормальному так и не придумал. Пока что пришло в голову получать значения через ссылку. Но тогда, геттар будет нормально работать только для членов класса, а вот например вернуть вычислимое значение уже проблематично, нужно искусственно делать возвращаемую переменную типом static. Да и к тому же возможны побочные эффекты - то есть после вызова геттера желательно в вызывающем коде сразу значение приравнять другой обычной переменной, чтобы она содержала копию данных, и эти данные уже не менялись если что-то в вызываемом классе изменится за счет других действий (например, после применений сеттеров). Пример, как работает геттер

Код:
public slots:
 void get_url(QString *url);

В главном окне связываю нужные виджеты, чтоб геттер работал

Код:
connect(pageview,SIGNAL(do_urlview_get_url(QString*)),urlview,SLOT(get_url(QString*));

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

Код:
QString url;
emit do_urlview_get_url(&url);


Но как-то это все криво, и мне не нравится, по описанным выше причинам.


Вопрос - как же реализовать геттер-сеттер  взаимодействие между виджетами, расположенными на главном окне? Может есть какой-то другой более правильный подход, о котором я незнаю? Расскажите, кто как организовывает свои приложения.

Записан

Собираю информацию по крупицам
http://webhamster.ru
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #1 : Октябрь 06, 2008, 12:11 »

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

Цитировать
У классов виджетов есть обычные public геттеры и сеттеры.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #2 : Октябрь 06, 2008, 12:53 »

ну вы и темы называете

Гете́ра (от греч. ἑταίρα — подруга, спутница) — в Древней Греции женщина, ведущая свободный, независимый образ жизни.[1] Известные гетеры были, как правило, хорошо образованы.

Итого:

  Сигналы, слоты, и реализация образованных женщин.
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #3 : Октябрь 06, 2008, 13:23 »

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

Цитировать
У классов виджетов есть обычные public геттеры и сеттеры.

Ну как же, чтобы использовать геттеры-сеттеры напрямую, нужно знать объект, у которого вызывать эти методы. А объекты в общем случае не должны знать, где находятся другие объекты, на которые они могут влиять, и от которых могут брать данные.

Это же получается, что виджет, чтобы установить значение в другом виджете, должен иметь такой код

parent()->urlview->set_url("http://prog.org.ru");

а если urlview окажется в другом месте, ну например войдет в состав более общего виджета, то в моем подходе нужно будет только централизованно подправить connect, а при "прямом" подходе нужно будет искать все классы, в которых есть вызовы геттеров/сеттеров, и менять пути до вызываемого виджета.

Но у меня подозрение, что я что-то не так делаю. Надо как-то по-другому, какой-то "обсервер" чтоли использовать, который будет принимать сигналы об изменении данных, и вызывать нужные слоты... Проблема в том, что не каждый слот надо вызывать при изменении данных в другом объекте, и логика вызова должна быть в том объекте где данные изменяются, а не выноситься в главное окно...
Записан

Собираю информацию по крупицам
http://webhamster.ru
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #4 : Октябрь 06, 2008, 13:35 »

Тогда объясние подробнее что это такое pageview и urlview. Это отдельные виджеты или классы?

А еще лучше, выложите минимальный код
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
zavulon
Гость
« Ответ #5 : Октябрь 06, 2008, 13:42 »

Я бы сделал геттер очень простым образом. Ничего замысловатого  не предлагаю.
У одного виджета геттер. У главного окна геттер "второго уровня", который использует геттер первого виджета. Все остальные виджеты в главном окне могут вызывать этот геттер "второго уровня" (если, конечно, имеют доступ к главному окну).

Пример (чисто схематически).

Код:
//Виджет с геттером:

class WidgetA
{
public:
const QString GetName() const
    { return name; }

private:
QString name;
};

class WidgetB;  // Ниже определение

// Главное окно, в котором все виджеты и находятся:

class MainWindow
{
public:
const QString GetWidgetAName() const
    { return widgetA.GetName(); }

private:
WidgetA widgetA;
WidgetB widgetB;
};

// Второй виджет, который хочет вызвать геттер первого:

class WidgetB
{
public:
WidgetB( MainWindow* aParent ): parent( aParent )
    {}

private:
MainWindow* parent;

void DoSomething()
    { QDebug() << parent->GetWidgetAName(); }
};
« Последнее редактирование: Октябрь 06, 2008, 13:46 от zavulon » Записан
Alex03
Гость
« Ответ #6 : Октябрь 06, 2008, 15:48 »

Но у меня подозрение, что я что-то не так делаю. Надо как-то по-другому, какой-то "обсервер" чтоли использовать, который будет принимать сигналы об изменении данных, и вызывать нужные слоты... Проблема в том, что не каждый слот надо вызывать при изменении данных в другом объекте, и логика вызова должна быть в том объекте где данные изменяются, а не выноситься в главное окно...
Вот и получается что вместо геттера одного объекта Вам нужен сеттер (ченджсигналлер) другого. Улыбающийся И в этом случае геттер может быть нужен только в начальный момент (в том же месте где и коннект()). Из возможных минусов такого подхода - необходимость хранить значения в объекте получателе сигнала. Как оптимальней зависит от задачи и /dev/head .
Я использую оба метода. В случае геттера через сигнал/слот необходимо обеспечить/контролировать наличие только одного коннекта к сигналу, либо разруливать ситуёвину иным способом, например передавать в сигнал ссылку на контейнер (тот же QStringList, QList<XXX> и т.д.) а в каждом слоте добавлять в этот контейнер данные.
Записан
ритт
Гость
« Ответ #7 : Октябрь 06, 2008, 15:56 »

молчал-молчал, но решил всё же написать Улыбающийся
я бы посоветовал организовать некий обсервер (можно глобальным синглтоном). для установки значений не потребуется дополнительных усилий; уведомления от обсервера можно получать посредством сигналов (после предварительной регистрации узла) и/или посредством рассылки (Custom|)Event'ов. во втором случае можно обойтись даже без регистрирования (ивентФильтры, рассылка через кореАппликейшен и т.д.)
Записан
SASA
Гость
« Ответ #8 : Октябрь 06, 2008, 16:55 »

Цитировать
Вопрос - как же реализовать геттер-сеттер  взаимодействие между виджетами, расположенными на главном окне? Может есть какой-то другой более правильный подход, о котором я незнаю? Расскажите, кто как организовывает свои приложения.
Q_PROPERTY, и ни каких connect'ов, указателей и т.д.
Код:
QString url = urlview->property("url");
urlview->setProperty("url","http://www.prog.org.ru");
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.146 секунд. Запросов: 22.