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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Как обработать сигнал одним слотом из подключенных?  (Прочитано 9343 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Сентябрь 01, 2014, 17:36 »

Есть несколько одинаковых объектов-приемников, у которых есть некий слот. Ко всем этим объектам подключен один сигнал одного объекта-источника, одновременно. В норме активация сигнала приводит к получению его всеми слотами и обработке всеми объектами этого класса. Точнее, всеми экземплярами объектов, как я сказал, их несколько. Но нужно, чтобы сигнал обработался только одним объектом, который получит сигнал первым, а остальные его проигнорировали. Проблема в том, что спецификатор static для создания разделяемого данного, и использования как семафора, не подходит - все объекты, это загруженные Qt-плагины. А в вениках, как известно, память данных у каждой DLL своя.

И отсюда вопрос - можно ли как-то внутри экземпляра объекта узнать, что он получил сигнал не первым? Вроде было такое где-то в QMeta???, но что-то не получается найти.
Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #1 : Сентябрь 01, 2014, 17:39 »

А зачем подключать слоты объектов к сигналу, если они его должны игнорировать?
Почему бы не подключать только один из объектов?
Записан
Bepec
Гость
« Ответ #2 : Сентябрь 01, 2014, 18:04 »

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

Но если опустить эту досадную особенность, то без координации тут никак - объекты должны знать хотя бы 1 общий ресурс в котором и будет разруливаться логика.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #3 : Сентябрь 01, 2014, 18:48 »

А зачем подключать слоты объектов к сигналу, если они его должны игнорировать?
Почему бы не подключать только один из объектов?

Разные объекты в плагинах, какие-то могут не быть загружены (отстуствовать в поставке). Могут присутствовать несколько. А обработать сигнал должен только один.
Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #4 : Сентябрь 01, 2014, 18:53 »

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

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

Что один и тот же - плевать, важно, чтобы сигнал не получили или проигнорировали остальные.

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

Вроде должно получиться с помощью invokeMethod(), поскольку реестр плагинов уже и так есть, достаточно пробежать по нему и с помощью invokeMethod() найти первый подходящий и не занятый плагин - кроме подходящих, есть еще и не подходящие, а у подходящего нить может быть занята обработкой.
« Последнее редактирование: Сентябрь 01, 2014, 19:01 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #5 : Сентябрь 01, 2014, 19:08 »

Можно проверять сигнал перед коннектом: если к нему уже кто-то подключен, то не подключаться.
bool QObject::isSignalConnected(const QMetaMethod & signal) const [protected]
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #6 : Сентябрь 01, 2014, 19:29 »

Можно проверять сигнал перед коннектом: если к нему уже кто-то подключен, то не подключаться.
bool QObject::isSignalConnected(const QMetaMethod & signal) const [protected]

Не, нельзя... Задача сложнее - первый, кто получил сигнал, становится занят на неопределенное время, за которое может прийти следующий сигнал, значит надо, чтобы сигнал получил другой, и обработал, если свободен. Слишком сложная получается логика подключений-отключений. Пока без invokeMethod не понятно, как это можно иначе сделать.
Записан

2^7-1 == 127, задумайтесь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #7 : Сентябрь 01, 2014, 22:01 »

Можно проверять сигнал перед коннектом: если к нему уже кто-то подключен, то не подключаться.
bool QObject::isSignalConnected(const QMetaMethod & signal) const [protected]

Не, нельзя... Задача сложнее - первый, кто получил сигнал, становится занят на неопределенное время, за которое может прийти следующий сигнал, значит надо, чтобы сигнал получил другой, и обработал, если свободен. Слишком сложная получается логика подключений-отключений. Пока без invokeMethod не понятно, как это можно иначе сделать.

Сделайте промежуточное звено (менеджер сигналов).. Пусть ловит сигналы и уже после (исходя из вашей задачи) перенаправляет их кому нужно и как нужно.. 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #8 : Сентябрь 02, 2014, 06:59 »

А нельзя ли объявить глобальную переменную-семафор, а при первом вызове метода осуществить дисконнект от прочих слотов?
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #9 : Сентябрь 02, 2014, 07:32 »

А нельзя ли объявить глобальную переменную-семафор, а при первом вызове метода осуществить дисконнект от прочих слотов?
Выстави QApplication::property().
Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Сентябрь 02, 2014, 08:47 »

Самое простое наверное и будет самым лучшим - подать флажок "принято" в параметрах сигнала. Напр использовать boost::optional
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #11 : Сентябрь 02, 2014, 10:31 »

Сделайте промежуточное звено (менеджер сигналов).. Пусть ловит сигналы и уже после (исходя из вашей задачи) перенаправляет их кому нужно и как нужно..  

В этом нет смысла, так менеджить сигналы можно было бы и в отправителе. Если бы можно было. Но такой вариант слишком усложняет реализацию.
« Последнее редактирование: Сентябрь 02, 2014, 10:35 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #12 : Сентябрь 02, 2014, 10:43 »

Самое простое наверное и будет самым лучшим - подать флажок "принято" в параметрах сигнала. Напр использовать boost::optional

boost не использую

сигнал - не объект, где у него есть состояние "принято"?

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

а разве нет?
Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #13 : Сентябрь 02, 2014, 11:32 »

Цитировать
Выстави QApplication::property().
qApp один на всю программу. Соответственно и флажок будет одним.
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #14 : Сентябрь 02, 2014, 11:39 »

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

Для больше безопасности её лучше завернуть в shared_ptr.

Код
C++ (Qt)
struct MySignalData
{
   bool processed;
   QString payload;
};
 
typedef QSharedPointer<MySignalData> MySignalDataPtr;
Q_DECLARE_METATYPE(MySignalDataPtr)
 
....
 
int main(int argc, char **argv)
{
   qRegisterMetaType<MySignalDataPtr>();
 
....
 
signals:
   void mySignal(MySignalDataPtr);
....
 
void mySlot(MySignalDataPtr data)
{
   if (data->processed)
       return;
   processData(data);
   data->processed = true;
}
 
« Последнее редактирование: Сентябрь 02, 2014, 11:42 от navrocky » Записан

Гугль в помощь
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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