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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как избежать бесконечного рекурсивного вызова слотов?  (Прочитано 4511 раз)
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« : Октябрь 22, 2013, 10:15 »

Иногда встречается ситуация, когда при смене значения в одном компоненте надо поменять значение в другом, и наоборот, например
Код
C++ (Qt)
connect(spinbox1, SIGNAL(valueChanged(int)), this, SLOT(slotValueChanged1(int)));
connect(spinbox2, SIGNAL(valueChanged(int)), this, SLOT(slotValueChanged2(int)));
void MyClass::slotValueChanged1(int i)
{
    spinbox2->setValue(i);
}
void MyClass::slotValueChanged2(int i)
{
    spinbox1->setValue(i);
}
Если не предпринять дополнительных мер, то слоты будут бесконечно вызывать друг друга.
Очевидны два метода решения
Первый - использовать метод QObject::blockSignals
Код
C++ (Qt)
void MyClass::slotValueChanged1(int i)
{
    this->blockSignals(true);
    spinbox2->setValue(i);
    this->blockSignals(false);}
 
void MyClass::slotValueChanged2(int i)
{
    this->blockSignals(true);
    spinbox1->setValue(i);
    this->blockSignals(false);
}
Считаю, что это плохое решение, т.к. блокируется весь механизм сигнал/слот, а не только те сигналы которые надо.

Другой вариант - ввести переменную, определяющую находимся ли мы уже внутри слота. Он не имеет недостатков первого метода, но имеет свои недостатки: много кода, на каждую пару слотов надо вводить отдельную переменную.
Код
C++ (Qt)
bool in_slot=false;
void MyClass::slotValueChanged1(int i)
{
    if(!in_slot)
    {
        in_slot=true;
        spinbox2->setValue(i);
        in_slot=false;
    }
}
void MyClass::slotValueChanged2(int i)
{
    if(!in_slot)
    {
        in_slot=true;
        spinbox1->setValue(i);
        in_slot=false;
    }
}
Есть ли какое-то стандартное решение для такой ситуации, не имеющее недостатков указанных решений?
Записан
mutineer
Гость
« Ответ #1 : Октябрь 22, 2013, 10:19 »

Вообще прямо в документации написано что чтобы избежать рекурсивного вызова слотов надо высылать сигнал об изменении только когда значение действительно изменилось, а не при каждой его записи
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #2 : Октябрь 22, 2013, 10:23 »

Пример с QSpinBox приведен для простоты.
На самом деле это может быть сложный самописный компонент, для которого не так просто проверить, изменилось в нём что-то или нет.
Записан
mutineer
Гость
« Ответ #3 : Октябрь 22, 2013, 10:24 »

Ну это все равно лучше, чем оба приведенных костыля
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #4 : Октябрь 22, 2013, 10:29 »

Мне кажется, что QSpinBox всегда шлёт сигнал при программной установке значения, даже если оно равно текущему.
Записан
mutineer
Гость
« Ответ #5 : Октябрь 22, 2013, 10:31 »

Это странно, в этом случае кутешники нарушают свои же рекомендации
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #6 : Октябрь 22, 2013, 10:35 »

Может я и ошибаюсь насчёт QSpinBox. В документации написано, что сигнала в этом случае нет.
Но сторонние компоненты могут нарушать эту рекомендацию.
Что можно сделать в таком случае?
Записан
mutineer
Гость
« Ответ #7 : Октябрь 22, 2013, 10:37 »

Делать проверку значения перед установкой и если оно такое же, то не ставить
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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