Какая правильная Qt-идиома для разоблачения сигналов/слотов содержащихся виджетов?
Предположим, что у меня есть MyWidget
, который содержит a MySubWidget
, например. пользовательский виджет, который содержит текстовое поле или что-то еще. Я хочу, чтобы другие классы могли подключаться к сигналам и слотам, которые были открыты с помощью экземпляра MySubWidget
. Это обычный способ сделать это:
- Выведите указатель на экземпляр
MySubWidget
с помощью метода subWidget()
в MyWidget
- Дублируйте сигналы и слоты
MySubWidget
в классе MyWidget
и напишите код пересылки
- Что-то еще?
Выбор 1 выглядит как наименьший код, но он также представляет собой разрывы инкапсуляции, так как теперь другим классам известно, что содержащиеся в нем виджеты MyWidget
являются и могут зависеть от их функциональности.
Выбор 2 кажется, что он хранит инкапсуляцию, но это много, казалось бы, избыточный и потенциально запутанный код, который искажает элегантность всей системы сигналов и слотов.
Что обычно делается в этой ситуации?
Ответы
Ответ 1
Если вы посмотрите на собственный код Qt, они предпочитают вариант 2.
Например, посмотрите QTabWidget и QTabBar. Они имеют ряд сигналов и слотов, но QTabWidget скрывает тот факт, что использует QTabBar (ну, sorta... QTabWidget::tabBar()
, очевидно, нарушает это, даже если он защищен).
Хотя это приведет к большему количеству кода, я думаю, что это стоит того, чтобы инкапсулировать.
Не забывайте, что вы можете подключать сигналы к таким сигналам:
connect(mySubWidget, SIGNAL(internalSignal(int)), this, SIGNAL(externalSignal(int)));
Что сделает MyWidget
emit externalSignal(int)
, когда MySubWidget
испускает internalSignal(int)
. Это помогает, по крайней мере, с сигнальной стороны вещей. К сожалению, я не знаю, какой простой способ сделать то же самое для слотов.
Ответ 2
Я бы не стал беспокоиться об инкапсуляции сигналов и слотов, по-видимому, только одна вещь делает соединение, так что вред в нем знает о некоторых подклассах? Если вы работаете над более крупной командой, предотвращая злоупотребление методом subWidget()
, вы можете сделать это с помощью ключевого слова friend или любого другого...
Ответ 3
Вы можете открыть базовый класс MySubWidget, который будет содержать меньше функциональности.