Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Ginger_Ministrel от Июль 17, 2014, 16:09



Название: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 17, 2014, 16:09
Суть такова: у нас есть программа, с большим ветвистым деревом объектов, создающих друг друга. Необходимо связать функции, находящиеся достаточно глубоко в разных ветках.

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

Ни одна из этих трех идей мне не нравится. Интересно узнать, как в таких случаях поступают суровые парни :33


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Bepec от Июль 17, 2014, 18:01
В чем проблема сделать сигнал в каждой ветке? А при создании просто цеплять к основе?
Каскадно получится :)


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 17, 2014, 19:18
На данный момент я вижу три варианта: либо делать все публичным и коннектить через десять стрелочек, либо каскадно сливать сигналы, заводя по сигналу в каждом объекте, который ближе к корню чем нужные, либо делать глобальный объект, который будет принимать и раздавать сигналы.
Давайте по рассуждаем.
Не важно, в какой структуре хранятся эти объекты. Сигналы-слоты связывают два объекта, значит нам нужны средства нахождения подходящих объектов для связывания. Само связывание можно делать в отдельной сущности (объекте), которая(ый) будет знать (уметь находить) нужные два объекта для связывания.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: _OLEGator_ от Июль 17, 2014, 22:41
Да, я бы делал через отдельный объект/менеджер.
Кстати, может пригодится, делал похожий механизм, но сейчас эту библиотеку не использую т.к. основная разработка не на Qt:
http://www.prog.org.ru/topic_24458_0.html

Там есть класс CXEventMachine, с помощью которого можно подписаться на произвольное событие (используется механизм сигналов/слотов). Событие испускается также с помощью этого класса и раздается всем подписанным.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 18, 2014, 11:35
Верес, технически проблемы в этом нет, но меня смущает нахождение в практически каждом классе сигналов, сделанных только для того, чтобы передавать другие сигналы ниже. В итоге в практически коренных классах будет тонна сигналов, по сути самому классу не нужных.

Old, собственно, к такому варианту я и склоняюсь. Вопрос в том, как его сделать и где создавать, чтобы все-все-все его видели. Синглтон со статическими функциями?

_OLEGator_, спасибо, сейчас гляну, что там.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 18, 2014, 11:39
Вопрос в том, как его сделать и где создавать, чтобы все-все-все его видели.
Для этого и нужны критерии, по которым вы принимаете решение связывать объекты. Опишите их подробней

Синглтон со статическими функциями?
Не надо эту гадость лишний раз тянуть в проект.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 18, 2014, 11:52
Например: в самом первом классе живет графический экран (QGraphicsView) и модули. В каждом модуле живет движок, в котором, в свою очередь, живет неопределенное количество графических сцен (QGraphicsScene). Нужно иметь возможность устанавливать экрану, какую сцену он отображает, причем запрос может поступить как от движка, так и от сцены или даже от объекта на сцене.

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


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 18, 2014, 11:55
Например: в самом первом классе живет графический экран (QGraphicsView) и модули. В каждом модуле живет движок, в котором, в свою очередь, живет неопределенное количество графических сцен (QGraphicsScene). Нужно иметь возможность устанавливать экрану, какую сцену он отображает, причем запрос может поступить как от движка, так и от сцены или даже от объекта на сцене.
А я бы тут подумал про событийную систему с широковещательными сообщениями: получат сообщение все, кому надо - отреагирует.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 18, 2014, 12:20
А как это лучше реализовать технически? Попробовал покурить QEvent, но то ли не докурил, то ли оно для этого не особо подходит.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 18, 2014, 12:31
А как это лучше реализовать технически? Попробовал покурить QEvent, но то ли не докурил, то ли оно для этого не особо подходит.
В самом примитивном случае вам нужно пробежаться по всем объектам и вызвать метод, например, eventHandle. Соответственно, у каждого объекта она должна быть, для этого проще всего сделать специальный класс и подмешать его для базового (базовых) классов всех возможных объектов.

Код
C++ (Qt)
enum EventType { Event1, Event2, ... }
 
class EventHandler
{
public:
   virtual void eventHandle( EventType event, void *param = 0 ) = 0;
};
 
 
class BaseObject : public QObject, public EventHandler
{
public:
   ...
   virtual void eventHandle( EventType event, void *param = 0 );
};
 

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


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Bepec от Июль 18, 2014, 12:47
А разве это не имитация сигнал слотовой системы Qt? :)


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 18, 2014, 12:51
А разве это не имитация сигнал слотовой системы Qt? :)
А в каком месте она имитируется?


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: kambala от Июль 18, 2014, 12:52
нет: в данном случае необязательно указывать источник сигнала.

кстати в Mac OS X есть такой механизм из коробки (NSNotificationCenter) :)


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Bepec от Июль 18, 2014, 13:00
Ошибся, точнее системы QEvent :)


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 18, 2014, 13:03
нет: в данном случае необязательно указывать источник сигнала.
В идеале хотелось бы сделать так, чтобы не нужно было и приемник сигнала указывать. Чтобы можно было не завязываться на то, какая там вообще в программе структура - просто если кто-то издает такой-то сигнал, то все, кому этого надо, начинают по нему выполнять действия.

В самом примитивном случае вам нужно пробежаться по всем объектам и вызвать метод, например, eventHandle. Соответственно, у каждого объекта она должна быть, для этого проще всего сделать специальный класс и подмешать его для базового (базовых) классов всех возможных объектов.
Насчет специального класса идею понял. А как это все обходить? По-любому понадобится какая-то глобальная штука, которая будет из конструкторов передавать в какой-то глобальный объект список всех объектов, а потом по сингналу тыкать.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 18, 2014, 13:13
Насчет специального класса идею понял. А как это все обходить? По-любому понадобится какая-то глобальная штука, которая будет из конструкторов передавать в какой-то глобальный объект список всех объектов, а потом по сингналу тыкать.
Опять же в простом случае, можно сделать статический список указателей на объекты, куда они сами будут вписываться/выписываться, и статическую функцию broadcast, которая будет пробегаться по этому списку и дергать нужный метод.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 18, 2014, 13:43
О, вот это хорошее решение на данный момент.
Хоть и не люблю я статические функции.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: _OLEGator_ от Июль 18, 2014, 14:24
Смотрю мой класс остался без внимания))


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Bepec от Июль 18, 2014, 14:28
Ну, так оно и бывает. Ухватываются за то, что ближе к их мыслям :)


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 18, 2014, 14:44
Смотрю мой класс остался без внимания))
Нет, почему. Я его просмотрел, но с ходу пока не понял, как он вообще работает. Поэтому я его отложил на покурить позднее, а пока занялся общей структурой проекта, которая почт не меняется в зависимости от сигнальной системы.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: _OLEGator_ от Июль 18, 2014, 15:41
Подписывание на событие:
Код
C++ (Qt)
CXEventMachine::subscribe(this, PRISM_EVENT(SelectData), PRISM_METHOD(setSelectData()));

Причем SelectData это по сути текстовая метка, это не сигнал и не слот. setSelectData - это слот.

Испускание события:
Код
C++ (Qt)
CXEventMachine::postEvent(PRISM_EVENT(SelectData));

Это события без параметров.

Есть возможность использовать до 3х параметров в событии:
Код
C++ (Qt)
CXEventMachine::postEvent<QString>(PRISM_EVENT(SelectData), "test");


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 18, 2014, 17:09
О! Реально похоже на то, что мне нужно. Попробую потыкать, посмотрим, что выйдет.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 22, 2014, 14:26
Я решил все-таки ради обучения написать свой вариант. Возник вопрос: как лучше реализовывать точку доступа?
Вижу два разных варианта. Первый - набор глобальных функций. Второй - аналогично QApplication: создаваемый в мэйне синглтон + глобальный указатель на него.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 22, 2014, 15:16
Первый - набор глобальных функций.
Наверное лучше класс с статическими членами.

Второй - аналогично QApplication: создаваемый в мэйне синглтон + глобальный указатель на него.
Если вы уверены, что такая система нужна одна на всю систему (а я не вижу смысла в нескольких), то хватит статических методов, но можно и синглетон завести.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Ginger_Ministrel от Июль 22, 2014, 15:52
Она нужна будет одна. По крайней мере, на данный момент я не вижу, зачем может понадобиться две разные системы связи удаленных объектов.
Синглтон больше подходит, потому что с одним и тем же массивом абонентов будет иметь дело несколько разных функций.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Old от Июль 22, 2014, 16:03
Синглтон больше подходит, потому что с одним и тем же массивом абонентов будет иметь дело несколько разных функций.
С массивом будет работать одна функция broadcast и две закрытых функции listen/unlisten (помещающая/удаляющая слушателя из массива). Их можно просто сделать статическими методами класса и все смогут к ним обращаться. Две последние я бы сделал закрытыми и подружил этот класс с базовым Object, что бы он мог регистрироваться в системе оповещения.


Название: Re: Глобальная система событий (обмен сигналами между ветками)
Отправлено: Fregloin от Июль 23, 2014, 10:10
Может здесь подойдет шаблон Медиатор?..