crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> [Решено] Как делать итемы, которые работают со сценой, но не должны там лежать?, Выделение и т.п.
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  


Цитата(Obey-Kun @ 26.3.2010, 4:31) *
Куда идеологически правильно помещать анкер и эти инструменты? Таки в сцену?
сам не пробовал, но мои размышления пришли к тому, что общую управляющую логику редактирования элементов удобнее помещать в само представление, т.к. это собственно виджет отображающий содержимое сцены. Добавь к этому саму идею разделения труда:
Модель (сцена) - Представление.
И представь, что к одной модели (сцене) подключено два представления. Тогда помещение общей управляющей логики внутрь элемента или сцены выглядит совсем неудачно.

Цитата(Obey-Kun @ 26.3.2010, 4:31) *
Надо ли наследовать прямоугольное и эллипсоидное выделение от 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 в ивент перемещения курсора запихано следущее:

emit cursorPositionChanged(mapToScene(event->pos()));
findAnchor(mapToScene(event->pos()));
/* фигня, которая, если активен какой-либо инструмент и если мы находимся у видимой границы, делает автоскрол */
QGraphicsView::mousePressEvent(event);


Сигнал cursorPositionChanged(QPointF) принимается в mainwindow, что приводит к изменению информации о координатах курсора в строке состояния.

Функция findAnchor(QPointF) посылает соответствующий сигнал в зависимости от возможности или невозможности привязки:
void Area::findAnchor(QPointF point) const
{
    QPoint point_to_anchor;
    if(tryAnchor1(point, point_to_anchor)) {
        emit anchorPositionChanged(point_to_anchor);
    } else {
        emit anchorIsNowNotPossible();
    }
}


Сигнал anchorPositionChanged(QPoint) принимается слотом сцены и меняет позицию анкера. Сигнал anchorIsNowNotPossible() принимается там же и прячем анкер.

P.S.: Функция bool View::tryAnchor1(const QPointF& point, QPoint& anchor_point) const — это попытка привязаться. Привязка довольно хитрая и учитывает не только шаг видимой сетки (!), но и кучу других параметров.

Забыл добавить, сигналы anchorPositionChanged(QPointF) и anchorIsNowNotPossible() принимаются перегруженным слотом anchorPosition:

void qfgui::Scene::anchorPosition(QPoint new_center)
{
    if(!m_main_anchor->isVisible()) {
        m_main_anchor->show();
    }
    m_main_anchor->setPos(new_center);
}

void qfgui::Scene::anchorPosition()
{
    m_main_anchor->hide();
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
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.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 19.4.2024, 12:43