Есть однопоточная программа.
Есть два контрола, полностью друг друга дублирующие. Не спрашивайте зачем. Так надо. Изменения в первом тут же отоьражаются на втором и наоборот.
Естественно уходим в зацикливание.
Да, булевский флаг вопрос решает. Типа в одном оботабоьчике поднимаем, во втором проверяем и выходим. Типа мьютекса. Но как-то это допотопно. Есть красивые современные решения?
Здравствуйте, Hоmunculus, Вы писали:
H>Есть однопоточная программа. H>Есть два контрола, полностью друг друга дублирующие. Не спрашивайте зачем. Так надо. Изменения в первом тут же отоьражаются на втором и наоборот. H>Естественно уходим в зацикливание. H>Да, булевский флаг вопрос решает. Типа в одном оботабоьчике поднимаем, во втором проверяем и выходим. Типа мьютекса. Но как-то это допотопно. Есть красивые современные решения?
Пусть сигнал "значение изменилось" порождается только если значение действительно изменилось, а не при каждом вызове setValue.
Здравствуйте, Hоmunculus, Вы писали:
H>Да, булевский флаг вопрос решает. Типа в одном оботабоьчике поднимаем, во втором проверяем и выходим. Типа мьютекса. Но как-то это допотопно. Есть красивые современные решения?
Мне знакома эта задача. Этот вопрос не имеет отношения к C++.
Не знаю "более красивых" решений, мне они неизвестны. Думаю, единственное нормальное рабочее решение — завести bool m_updatingControls, чтобы потом его проверять в обработчиках TextChanged или ValueChanged, но тут ещё важно следить за тем чтобы не было логики в контролах (иначе запутаешься, разруливая диспатчинг).
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Hоmunculus, Вы писали:
H>Есть однопоточная программа. H>Есть два контрола, полностью друг друга дублирующие. Не спрашивайте зачем. Так надо. Изменения в первом тут же отоьражаются на втором и наоборот. H>Естественно уходим в зацикливание. H>Да, булевский флаг вопрос решает. Типа в одном оботабоьчике поднимаем, во втором проверяем и выходим. Типа мьютекса. Но как-то это допотопно. Есть красивые современные решения?
Определить понятие "источник изменения". Если им является парный контрол, то не сообщать ему об изменении. Сообщать только если источником является некто третий.
Кстати, если C#, то там в любом обработчике есть параметр Sender.
В C# sender — это, как правило, первый параметр в методах обработки событий (event handler), ссылающийся на объект, который инициировал событие. Он имеет тип object, позволяя определить, какой конкретно элемент управления (например, кнопка) вызвал код. Используется в механизме EventHandler для управления событиями.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Определить понятие "источник изменения". Если им является парный контрол...
Очень плохая идея! Контрол не должен знать о существовании других контролов, в идеальном случае вообще не знать, ни при каких обстоятельствах Для последнего лучше всего заводить GUI-manager, который будет поставлять контролы и диалоги. Это уменьшает связность и позволяет реиспользовать контролы. Если у тебя один контрол прибит к другому, то править код сложно, использовать контролы в другом месте (напр. в другом проекте) тоже сложно.
Моя практика показала, что использование Sender — плохая идея. А вот надстройка над моделью — ViewModel — хорошая. Это стоит делать, даже если это не WPF, и MVVM для этого конкретного фрэйморка чужеродно. Задача ViewModel — адаптировать модель так, чтобы её мог отобразить и другим способом использовать контрол. Sender стоит использовать только для того, чтобы из него вытаскивать хэндл для ParentControl или ParentWindow: не стоит через него делать логику отображения. Использование INotifyPropertyChanged или INotifyCollectionChanged из ViewModel — тоже хорошая идея.
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Философ, Вы писали:
Ф>Очень плохая идея! Контрол не должен знать о существовании других контролов, в идеальном случае вообще не знать, ни при каких обстоятельствах
В теории да, но не всегда стоит строго следовать ей. И в данном случае, мне кажется, это будет самое простое решение, буквально из 1-2 строк.
По сути тут некий неявный класс "парный контрол". Можно его и явным сделать (для того, чтобы удовлетворить высокой теории ), и тогда вопрос о том, кто что знает, снимается сам собой.
Здравствуйте, Pavel Dvorkin, Вы писали:
Ф>>Очень плохая идея! Контрол не должен знать о существовании других контролов, в идеальном случае вообще не знать, ни при каких обстоятельствах PD>В теории да, но не всегда стоит строго следовать ей. И в данном случае, мне кажется, это будет самое простое решение, буквально из 1-2 строк.
На практике: практика показывает, что правила всё-таки нужны. На старте может показаться, что скоростное решение в 2 строки сдесь годится, но уже через год ты жалеешь о том, что поддался соблазну написать "быстро". Вот это "быстро сейчас" потом оборачивается головной болью. Это дурацкая привычка, писать как быстрее в данный момент, не задумываясь о будущем — о том, как ты это будешь потом поддерживать.
PD>По сути тут некий неявный класс "парный контрол"...
Это он в данном контексте парный, но контекст может поменяться, притом с высокой вероятностью. Нельзя связывать контролы напрямую — только через промежуточный объект, и лучше, если это будет специально приспособленный объект, отвечающий за подготовку данных для отображения. Иначе потом развязывать сложно. Иначе потом будет ещё одно костыльное решение, а потом ещё одно, и ещё...
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Философ, Вы писали:
Ф>На практике: практика показывает, что правила всё-таки нужны. На старте может показаться, что скоростное решение в 2 строки сдесь годится, но уже через год ты жалеешь о том, что поддался соблазну написать "быстро". Вот это "быстро сейчас" потом оборачивается головной болью. Это дурацкая привычка, писать как быстрее в данный момент, не задумываясь о будущем — о том, как ты это будешь потом поддерживать.
А с другой стороны, ты можешь потратить несколько дней на создание "правильной архитектуры" вместо костыля, а применив на практике, сразу поймешь, что это не то, что нужно, и все труды насмарку. Костыль может быть хорошим инструментом для исследования. Главное вовремя их рефакторить, когда теория более-менее устаканивается.
Здравствуйте, graniar, Вы писали:
G>А с другой стороны, ты можешь потратить несколько дней на создание "правильной архитектуры" вместо костыля, а применив на практике, сразу поймешь, что это не то, что нужно, и все труды насмарку. Костыль может быть хорошим инструментом для исследования. Главное вовремя их рефакторить, когда теория более-менее устаканивается.
Дело в том, что вовсе не обязательно "создавать архитектуру" — в большинстве случаев достаточно придерживаться базовых принципов и базовых целей. Например, базовая цель: низкая связность. Она даёт возможность реиспользовать компоненты, из обратного: высокая связность мешает отодрать от решения какой-то компонент для того, чтобы использовать его в другом месте или в ином качестве. Для уменьшения связности существуют уже зарекомендовавшие себя решения — паттерны проектирования. Если ты читал банду четырёх, то знаешь — паттерны проектирования они определили именно так. Ещё базовый принцип: SRP — в дальнейшем позволяет вносить точечные изменения, не затрагивая другие части системы. Например, для изменения отображения отдельного компонента изменение вносится только в код отображения и гарантированно не ломает бизнес-логику.
Пытаясь следовать этим целям и принципам ты автоматически делаешь удобоваримую архитектуру, не особо тратясь на её "изобретение".
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Философ, Вы писали:
Ф>Дело в том, что вовсе не обязательно "создавать архитектуру" — в большинстве случаев достаточно придерживаться базовых принципов и базовых целей. Например, базовая цель: низкая связность. Она даёт возможность реиспользовать компоненты, из обратного: высокая связность мешает отодрать от решения какой-то компонент для того, чтобы использовать его в другом месте или в ином качестве.
Я думаю это скорее вопрос привычки. Мне просто в голову не придет проектировать какой-то объект так, чтобы он знал о чем-то, что ему не нужно для своей работы.
Но иногда, для отладки или эксперимента, возникает потребность временно воткнуть костыль, могу даже член класса воткнуть, без отступа пишу, чтоб сразу было видно что ему тут не место.
Или в код библиотеки могу воткнуть пользовательский инклуд, привести объект к производному классу и закинуть инфу в лог.
И как ни странно не ощущаю себя святотатцем. Разве что иногда можно ворнинг добавить, чтоб не забыть прибраться потом.
Здравствуйте, Hоmunculus, Вы писали:
H>Да, булевский флаг вопрос решает. Типа в одном оботабоьчике поднимаем, во втором проверяем и выходим. Типа мьютекса. Но как-то это допотопно. Есть красивые современные решения?
Qt решает эту проблему просто: если новое и старое значения совпадают, оповещение "значение изменилось" не создается, каллбаки не дергаются.
т.е. первым делом в местоде setValue делается проверка
if ( newValue == value() )
return;
и тогда любое зацикливание разрывается автоматически.