Название: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Fregloin от Август 11, 2011, 15:46 Есть сцена, на которой куча объектов (светофоры, пути, индикаторы и прочее).
В программе есть несколько режимов работы. Один из режимов - режим редактирования, в котором на сцену можно кидать новые элементы, удалять их, перемещать, копировать/вставлять и т.п. Следующие режимы - режимы исполнения программы, на сцене элементы уже фиксированы. Мне нужно для каждого из режимов переопределить поведение сцены на: -нажатие,отпускание,перемещение мыши -нажатие клавы -скроллинг колесиком. Сначала я делал так: в некой переменной хранил текущий тип режима работы, и в зависимости от его значения по switch вызывал функции обработки событий для данного режима работы. Но у такого подхода недостаток, что при добавлении нового режима приходится лезть внуть сцены и править функции-обработчики мышы/клавы что крайне неудобно. Решил сделать так, объявить сигналы нажатия,движения,отпускания мыши, emit их в виртуальных функциях-обработчиках сцены, а уже в кажом режиме подключать свои слоты (нечто подобного реализовано в Delphi через события объекта). Все работает, но при движении мыши проц грузится нешуточно,я так понимаю изза частого emit. Я уже ставил и Qt::DirectConnection - не помогает. Подскажите, как можно грамотно организовать полиморфизм этих обработчиков для сцены. В будущем планирую все режимы вывести в отдельные плагины. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Fregloin от Август 11, 2011, 15:52 как было раньше:
Код: void QEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Код: class QExGraphicsScene : public QGraphicsScene а в каждом режиме работы (считай плагине) Код: void CArmEditor::createLogic() Но последний подход к сожалению дико тормозит. Можно ли в Qt как то грамотно реализовать мою задачу? Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Fregloin от Август 11, 2011, 15:53 Ибо с перым подходом я уже влажу в такие дебри, и теряется универсальность,расширяемость программы (о плагинах и речи идти не может, а надо)
Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Igors от Август 11, 2011, 16:08 Ситуация может быть хуже, напр. в режиме редактирования объекты можно выбирать и двигать, а в режиме просмотра - только выбирать. Я задавал подобный вопрос неск месяцев назад. Насколько помню, ответы были
- использовать QStateMachine (без указания деталей) - навесить фильтры (в зависимости от режима). Ну как-то помогает, но не более того Склоняюсь к мысли что это проблема "архитектурно-концептуальная", т.е.. не решается каким-то конкретным классом/тулзом. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: brankovic от Август 11, 2011, 18:06 Код: как сделал сейчас можно вынести полиморфизм в отдельный класс, например так: Код
тогда Actor будет работать с QExGraphicsScene как с внешним классом. Пусть некая лишняя писанина, но зато код edit и view режима будет лежать отдельно в ActorEdit и ActorView. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: _OLEGator_ от Август 11, 2011, 18:17 Я вижу это так:
1) Реализовать для сцены абстрактный класс обработки событий, в который будут передаваться события и устанавливаться сцена, возможно еще какие данные. Для каждого режима реализовать свои классы, унаследованные от абстрактного. Устанавливать в сцену экземпляр нужного класса. (brankovic предложил выше) или 2) Реализовать один менеджер, в который вынести режимы и обработку событий. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Igors от Август 11, 2011, 19:18 тогда Actor будет работать с QExGraphicsScene как с внешним классом. Пусть некая лишняя писанина, но зато код edit и view режима будет лежать отдельно в ActorEdit и ActorView. Этот книжный приемчик мало помогает когда проект разрастается. Два и более обработчиков начинают иметь все более и более общего что трудно (или невозможно) вынести в методы их базового класса. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: brankovic от Август 11, 2011, 20:14 Этот книжный приемчик мало помогает когда проект разрастается. Два и более обработчиков начинают иметь все более и более общего что трудно (или невозможно) вынести в методы их базового класса. Ммм.. это Вы про проблемы C++ в целом или данного конкретного решения? В любом случае я всегда за лучшие альтернативы. У Вас какие предложения, напомните? Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: iroln от Август 11, 2011, 20:49 Ситуация может быть хуже, напр. в режиме редактирования объекты можно выбирать и двигать, а в режиме просмотра - только выбирать. Я задавал подобный вопрос неск месяцев назад. Насколько помню, ответы были Вот у меня ситуация один в один. В режиме редактирования объекты можно модифицировать, в режиме просмотра их можно выбирать и подсвечивать. И тоже столкнулся с проблемой фильтрации событий мышки и клавиатуры. Сейчас пока сделал как автор темы, задал переменную режима работы, но мне это тоже не нравится. Если здесь предложат красивое верное решение, буду рад его использовать, а пока буду тоже думать. :)- использовать QStateMachine (без указания деталей) - навесить фильтры (в зависимости от режима). Ну как-то помогает, но не более того Склоняюсь к мысли что это проблема "архитектурно-концептуальная", т.е.. не решается каким-то конкретным классом/тулзом. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Igors от Август 12, 2011, 08:12 Ммм.. это Вы про проблемы C++ в целом или данного конкретного решения? Данного конкретного. Где фильтроваться? На уровне application - так оно отдает события окнам. На уровне окна - так их могут быть десятки, любой немодальный диалог. Как фильтроваться? Напр что должен делать ActionView::KeyDown? Заблокировать весь ввод - не годится, что-то вводить можно и в режиме просмотра. Заблокировать некоторые клавиши? Так это зависит от фокуса. Перебирать на фильтре "какой контрол сейчас в фокусе" выглядит совсем глупо, уж лучше сделать у окна метод вроде SetViewMode() где задизаблить что надо (тоже впрочем не фонтан)Ситуация с MouseDown гораздо хуже, потому что часто куда проще драгаться именно в MouseDown (не бегая с флажками в MouseMove). В MouseDown удобно зарядить ряд scoped и крутить драг с вторичным циклом событий. Но при этом разборка view/edit проникает на самый нижний уровень :'( В любом случае я всегда за лучшие альтернативы. У Вас какие предложения, напомните? Разве я от Вас стал бы скрывать если б знал? :) Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Igors от Август 12, 2011, 14:34 Вот примерчик:
- есть окно, а в нем банальный листбокс. Выбранные айтемы могут быть перемещены (внутри листбокса) драгом, удалены с помощью клавиши Del или если пользователь открыл контекстуальное меню и выбрал там delete. По нажатию спец-клавиши (напр Enter) появляется inline-editor и имя айтема можно поменять Понятно что в режиме view удаление и изменение имени должны быть запрещены, но как это сделать "на уровне окна"? (mouse/key-события) Запретим драг? Но он может иметь смысл и для view. Запретим вызов контекстуального меню - тоже не годится, там должно быть только задизаблено delete. Запретим inline-edit? А откуда мы знаем какая клавиша его включит? Напр для др. листбокса редактирование начинается по dbl-click. Др. словами мы навесили обработчик который пытается управлять тем чего он не знает. А вот когда мы "спустимся" на уровень листбокса - все прекрасно, у него-то все на руках и ему отлично известно что должно быть вкл/выкл в зависимости от режима. Но так мы ничего не выигрываем по сравнению с тупеньким if/switch. Ситуация легко проецируется на QGraphicsScene и многие др случаи. Но вероятно я "ударился в концептуальность" (бывает), и это никому не интересно :) Edit: вспомнился старый анекдот по поводу view/edit Цитировать (Большой грабитель) Всем оставаться на своих местах! Сейчас будем грабить и насиловать! (Маленький грабитель) Только грабить! (Женщина в переднем ряду) А ты, маленький, помолчи... Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: iroln от Август 12, 2011, 15:11 Ситуация легко проецируется на QGraphicsScene и многие др случаи. Но вероятно я "ударился в концептуальность" (бывает), и это никому не интересно :) Да вообще-то как раз интересно. Потому что часто не очень понятно как сделать так, чтобы было концептуально правильно, гибко, расширяемо, и т.д. Возможно из-за нехватки опыта, возможно из-за недостаточных навыков проектирования, я часто застреваю на таких вот штуках. :)Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: _OLEGator_ от Август 12, 2011, 18:43 Я, честно говоря, не понимаю о чем спор.
Был предложен вариант решения, когда все эти switch сгруппировать и вынести в отдельный класс. Реализовать несколько классов под различное поведение, а потом прогонять все события через него и менять их под нужные режимы. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Fregloin от Август 15, 2011, 11:28 ну а как это сделать так, что бы все классы наследники сцены и режимы работы вынести в отдельные плагины, так как предвидится 3 и более режимов работы программы, на каждый режим хочется свой плагин. Пока все в одной куче.
Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Fregloin от Август 15, 2011, 12:22 решил пойти путем создания делегатов, но увы результат тот же - жуткие тормоза при событиях мыши...
Код: #ifndef QEXGRAPHICSSCENE_H Код: #include <QGraphicsSceneMouseEvent> вот класс-логики редактора Код: ... вот привязка в режиме редактирования Код: void CArmEditor::createLogic() вот обработчики Код: void CArmEditor::fieldMousePressed(QExGraphicsScene * scene, QGraphicsSceneMouseEvent *event) Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Fregloin от Август 15, 2011, 12:39 и хотя такой подход работает, но изза использования статических функций нет возможности испускать нужные мне сигналы ...
придется пробовать подход с SceneActor. Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Fregloin от Август 16, 2011, 09:01 да, забыл уточнить, у меня есть два типа view и scene, у каждого из них своя логика отрисовки, соответсвтенно они разных классов.
Название: Re: Как грамотно организовать полиморфизм поведения QGraphicsScene Отправлено: Akon от Август 21, 2011, 19:36 Я вижу это так: 1) Реализовать для сцены абстрактный класс обработки событий, в который будут передаваться события и устанавливаться сцена, возможно еще какие данные. Для каждого режима реализовать свои классы, унаследованные от абстрактного. Устанавливать в сцену экземпляр нужного класса. (brankovic предложил выше) или 2) Реализовать один менеджер, в который вынести режимы и обработку событий. + Это обычный паттерн стратегия (абстрактный класс обработки событий для сцены). Добавляется новый режим - добавляется новая стратегия. Всякие if/switch в любом месте это уход от полиморфизма. |