[Решено] Как делать итемы, которые работают со сценой, но не должны там лежать?, Выделение и т.п. |
Здравствуйте, гость ( Вход | Регистрация )
[Решено] Как делать итемы, которые работают со сценой, но не должны там лежать?, Выделение и т.п. |
Obey-Kun |
26.3.2010, 1:31
Сообщение
#1
|
Студент Группа: Участник Сообщений: 96 Регистрация: 24.3.2010 Пользователь №: 1556 Спасибо сказали: 3 раз(а) Репутация: 0 |
У меня унаследованы от Qt'шных свои View и Scene.
На данный момент делаю различные инструменты: прямоугольное выделение, эллипсоидное выделение, полигональное выделение (всё в стиле GIMP). Также существует анкер-привязка (как в Автокаде). Сейчас я их кладу в сцену, т.к. так получается их перерисовывать. Например, бывает нужно переместить анкер и тогда я посылаю сигнал anchorPositionChanged(QPoint). Или юзер хочет изменить размер прямоугольного выделения, тогда он берёт и тащит за угол, что приводит к посыланию соответствующих сигналов. Куда идеологически правильно помещать анкер и эти инструменты? Таки в сцену? Надо ли наследовать прямоугольное и эллипсоидное выделение от QRubberBand, или от чего тогда? Сообщение отредактировал Obey-Kun - 28.3.2010, 0:56 |
|
|
Litkevich Yuriy |
26.3.2010, 1:45
Сообщение
#2
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
Куда идеологически правильно помещать анкер и эти инструменты? Таки в сцену? сам не пробовал, но мои размышления пришли к тому, что общую управляющую логику редактирования элементов удобнее помещать в само представление, т.к. это собственно виджет отображающий содержимое сцены. Добавь к этому саму идею разделения труда:Модель (сцена) - Представление. И представь, что к одной модели (сцене) подключено два представления. Тогда помещение общей управляющей логики внутрь элемента или сцены выглядит совсем неудачно. Надо ли наследовать прямоугольное и эллипсоидное выделение от QRubberBand, или от чего тогда? я думаю, что это разумно, т.к. новоиспечённый класс можно будет передавать в качестве параметра, тем функциям, которые принимают QRubberBand
|
|
|
Obey-Kun |
26.3.2010, 2:07
Сообщение
#3
|
Студент Группа: Участник Сообщений: 96 Регистрация: 24.3.2010 Пользователь №: 1556 Спасибо сказали: 3 раз(а) Репутация: 0 |
А как тогда сделать динамически перемещаемый прямоугольник, который можно прятать и показывать (это нужно для анкера)? Через сцену легко — наследуем QGraphicsItem и делаем нужный paint()...
|
|
|
Obey-Kun |
26.3.2010, 3:05
Сообщение
#4
|
Студент Группа: Участник Сообщений: 96 Регистрация: 24.3.2010 Пользователь №: 1556 Спасибо сказали: 3 раз(а) Репутация: 0 |
Смотрите, хорошо сделано или нет?
Есть View. У него размер сетки зависит от масштаба. Анкер должен привязываться в зависимости от видимого размера сетки. В этом View в ивент перемещения курсора запихано следущее:
Сигнал cursorPositionChanged(QPointF) принимается в mainwindow, что приводит к изменению информации о координатах курсора в строке состояния. Функция findAnchor(QPointF) посылает соответствующий сигнал в зависимости от возможности или невозможности привязки:
Сигнал anchorPositionChanged(QPoint) принимается слотом сцены и меняет позицию анкера. Сигнал anchorIsNowNotPossible() принимается там же и прячем анкер. P.S.: Функция bool View::tryAnchor1(const QPointF& point, QPoint& anchor_point) const — это попытка привязаться. Привязка довольно хитрая и учитывает не только шаг видимой сетки (!), но и кучу других параметров. Забыл добавить, сигналы anchorPositionChanged(QPointF) и anchorIsNowNotPossible() принимаются перегруженным слотом anchorPosition:
|
|
|
Obey-Kun |
26.3.2010, 5:18
Сообщение
#5
|
Студент Группа: Участник Сообщений: 96 Регистрация: 24.3.2010 Пользователь №: 1556 Спасибо сказали: 3 раз(а) Репутация: 0 |
Правильно ли я задумал реализацию инструментов?
Инструменты бывают трёх типов — рисующие в сцене, выделяющие элементы сцены и изменяющие камеру (зум и перетаскивание видимой области). Привязка нужна только для рисующих и выделяющих инструментов, но не для изменяющих камеру. Так как логика привязки лежит во View, значит от должен знать о текущем инструменте. Итак. В одном из тулбаров mainwindow юзер выбирает инструмент. Посылаем сигнал toolChoosen(InstrumentType::type). InstrumentType::type -- это элемент enum'а из хедера с константами. Этот сигнал поймался во View и он запомнил выбранный инструмент, что позволяет включить или выключить привязку (а также выбрать нужный способ привязки). Во View в ивенте нажатия левой кнопки мыши написан switch, который посылает сигнал типа startInstrument(InstumentType::rectangleSelection), startInstrume(InstumentType::createCellsInRectangle), или startInstrume(InstumentType::zoomOut). Сигнал ловится в сцене и она создаёт соответствующую фигуру. Во View в ивенте перемещения для нажатой левой кнопки мыши отправляется сигнал setInstrumentCorner(QPointF new_position). Сигнал ловится в сцене и она изменяет фигуру активного инструмента. Во View в ивенте перемещения для нажатой левой кнопки мыши отправляется сигнал setInstrumentCorner(QPointF new_position). Сигнал ловится в сцене, она отправляет или InstrumenFailure() (это значит, что то, что попытался сделать юзер, делать нельзя), или InstrumentSuccesfull(QRectF instrument_rect), после чего удаляет созданный инструмент. View принимает этот сигнал и, если принятый сигнал -- InstrumentSuccesfull(QRectF), делает нужное действие основываясь на instrument_rect и выбранном инструменте (опять switch). То есть или изменяет свой масштаб, или посылает соответствующий сигнал в сцену (что-то вроде createRectangles(QRectF zone, QSize rectangles_size) для инструмента, рисующего прямоугольники), или создаёт соответствующий path и делает select в сцене. Нормально? Цитата Во View в ивенте перемещения для нажатой левой кнопки мыши отправляется сигнал setInstrumentCorner(QPointF new_position). Сигнал ловится в сцене, она отправляет или InstrumenFailure() (это значит, что то, что попытался сделать юзер, делать нельзя), или InstrumentSuccesfull(QRectF instrument_rect), после чего удаляет созданный инструмент. Опечатка. Имелось в виду Цитата Во View в ивенте перемещения для нажатой левой кнопки мыши отправляется сигнал instrumentDone(). Сигнал ловится в сцене, она отправляет или InstrumenFailure() (это значит, что то, что попытался сделать юзер, делать нельзя), или InstrumentSuccesfull(QRectF instrument_rect), после чего удаляет созданный инструмент. тьфу, опять не так... в общем, Цитата Во View в ивенте отпускания левой кнопки мыши отправляется сигнал instrumentDone().
Сигнал ловится в сцене, она отправляет или InstrumenFailure() (это значит, что то, что попытался сделать юзер, делать нельзя), или InstrumentSuccesfull(QRectF instrument_rect), после чего удаляет созданный инструмент. |
|
|
Obey-Kun |
26.3.2010, 16:47
Сообщение
#6
|
Студент Группа: Участник Сообщений: 96 Регистрация: 24.3.2010 Пользователь №: 1556 Спасибо сказали: 3 раз(а) Репутация: 0 |
Я всё понял. Просто и логично.
Представим, что у нас несколько View. Если нужно, чтобы инструмент рисовался во всех view, то кладём его в сцену. Иначе используем QRubberBand (ну или нечто унаследованное от него, как я понимаю не проблема сделать что угодно: полигон, овал, прямоугольник). Это отлично видно в 40000 chips. |
|
|
Текстовая версия | Сейчас: 19.4.2024, 12:43 |