Название: QGraphicsView/Scene Отправлено: Khs от Декабрь 21, 2008, 23:13 Привет всем! Вроде просмотрел все топики в этом форуме касающиеся данного вопроса, но нормального ответа не нашел.
1. Чем отличается setBackgroundBrush(...) у QGraphicsView от аналогичной функции setBackgroundBrush(...) у QGraphicsScene, и что является предпочтительнее. Например в моем случае, я делаю карту страны, на которой буду размещать объекты - дороги, города и тп. И я хотел в background поместить пустую карту страны (чтобы на ней уже потом размещать магистрали и тп.). 2. При установке изображения в background QGraphicsView/QGraphicsScene, изображение множество раз повторяется (тоесть как будто матрица изображений получается). А я хотел бы чтобы оно отображалось 1 раз. Как это реализовать? 3. Какой тип карты лучше использовать, векторный или растровый?! 4. В случае растрового изображения, поместить его в background QGraphicsView/QGraphicsScene не проблема вроде. А как быть с векторным изображением? Название: Re: QGraphicsView/Scene Отправлено: Rcus от Декабрь 21, 2008, 23:47 1. отличие в том что у сцены может быть несколько отображений. Метод QGraphicsScene::setBackgroundBrush() задает кисть для всей сцены, метод QGraphicsView::setBackgroundBrush() задает кисть для конкретного отображения. В описанном случае я бы вообще использовал ::drawBackground()
2. см. п.1 3. "this depends on.." Ваша задача не нова, можно изучить решения предшественников. 4. если изображение в формате svg, то в Qt есть модуль его поддержки Название: Re: QGraphicsView/Scene Отправлено: Khs от Декабрь 21, 2008, 23:52 п.1 Ну а если сцена одна и вид один, есть ли разница где рисовать фон?!
п.3, Я в курсе что вопрос не новый, просто хотел услышать совета от людей которые этим сами занимались. п.4, Да, я видел классы для svg, но не совсем понял, как мне все это дело потом отобразить в QGraphicsView. Надо будет еще разок посмотреть. Кто еще что посоветует?! - Такс, ну вроде разобрался :) Название: Re: QGraphicsView/Scene Отправлено: AAXEE от Декабрь 25, 2008, 17:05 1. Вроде так:
Представь, что сцена квадратная, и она целиком внутри прямоугольной(не квадратной) view. Так вот фон у сцены будет занимать квадрат, а фон view будет тот, что вне сцены, но внутри view( полоски по краям). Название: Re: QGraphicsView/Scene Отправлено: Khs от Декабрь 25, 2008, 22:36 Ага, я уже разобрался, но все равно спасибо ;)
Буду задавать здесь другие вопросы по мере разработки проги :) Название: QGraphicsView/Scene Отправлено: Khs от Декабрь 26, 2008, 14:47 Такс, назрел еще один вопрос.
Во всяких геосистемах есть такая функция, как увеличение определенного участка карты (тоесть выделяешь мышкой какой то прямоугольник на карте и экран автоматически центруется на этом участке и он увеличивается..). Так же хочу сделать и я у себя, я так полагаю, после выделения участка, необходимо чтобы он отцентровался на области, и там уже применить scale(). Или это делается как то проще?! Название: Re: QGraphicsView/Scene Отправлено: QCasper от Декабрь 26, 2008, 14:53 QGraphicsView::centerOn() ?
Название: Re: QGraphicsView/Scene Отправлено: Khs от Декабрь 26, 2008, 15:10 Точно! Спасибо! :)
Название: QGraphicsView/Scene Отправлено: Khs от Декабрь 27, 2008, 13:50 Имею 3 своих класса, например, classMainWindow (главное окно, на нем размещен тулбар) унаследован от QMainWindow, classGraphicsView (отображается в главном окне) унаследован от QGraphicsView , classGraphicsScene (сцена своего отображения) унаследован от QGraphicsScene.
Так вот, на тулбаре допустим 3 кнопки (b1, b2, b3) - Они являются переключателями режима редактирования для GraphicsView/Scene, тоесть режим поворота, зума и тп. Так вот, как лучше сделать связь. Я предполагаю так, на сигнал нажатия кнопки, вызывается соответствующий слот (например slot_rotate(), slot_zoom() и тп). Рассмотрю на одном слоте. Допустим slot_zoom() { // В классе classMainWindow имеются указатели на объект класса classGraphicsView/Scene // m_view, m_scene например... // здесь меняю курсор у сцены на соответствующий режиму зума через m_scene->setCursor() // теперь нужно чтобы при клике на Scene, выполнялось действие соответствующее // включенному режиму. // Здесь собственно и хотел бы узнать как лучше сделать. // Я думаю сделать так, создать какие то флаги - соответствующие режимам, создать в // классе classGraphicsScene метод, например setFlag(int flag), и в вызванном слоте, в данном // случае slot_zoom() вызывать m_scene->setFlag(zoom_flag). А в переопределенном // mousePress в классе classGraphicsScene уже делать switch(flag) и производить необходимые // действия в зависимости от режима. } Так вот, моя реализация буит правильной? или есть более умные пути к решению данной задачки..?! Название: Re: QGraphicsView/Scene Отправлено: BRE от Декабрь 27, 2008, 14:29 Можно так. Вообще можно придумать много вариантов.
Например, можно в classMainWindow добавить сигнал changedState( State ), который подключать ко всем, кому необходимо отслеживать изменение состояния. Название: Re: QGraphicsView/Scene Отправлено: BRE от Декабрь 30, 2008, 09:40 Как вариант, можно сделать что-то типа:
Код
А в соответствующих обработчиках событий classGraphicsScene: Код
Смена режима, это изменение указателя currentState на объект соответствующего класса. Название: QGraphicsView/Scene Отправлено: Khs от Декабрь 30, 2008, 17:45 Ну да, по сути можно по-разному все это реализовать, просто я когда спрашивал, хотел узнать как будет оптимальней :)
Название: Re: QGraphicsView/Scene Отправлено: Khs от Январь 13, 2009, 10:17 Итак, возник вопрос из той же темы :)
Структуру классов описывал выше. Так вот. Сделал так. В главном окне класса classMainWindow, создал тулбар, на котором имеется допустим 5 тулбаттонов (каждая кнопка это какой-то режим, тоесть задействован может только 1 режим). На группу (QButtonGroup *toolsGroup) повесил коннект: connect(m_toolsGroup, SIGNAL(buttonClicked(int)), SLOT(toolsGroupClicked(int))); , где: void classMainWindow::toolsGroupClicked(int) { m_mapScene->setMode(classGraphicsScene::Mode(m_toolsGroup->checkedId())); } Тоесть в зависимости от переключателя в классе сцены устанавливается режим (зум, поворот иль т.п.) В классе сцены соответственно имеется слот: void classGraphicsScene::setMode(Mode mode) { m_Mode = mode; switch(m_Mode) { case mode_zoomin: // break; case ... ... } } Тоесть здесь устанавливается режим в сцене и при событии mousePressEvent(...) в зависимости от режима, выполняются действия (либо со сценой, например размещение элемента на сцене, либо со вьюшкой, тоесь поворот, либо зум). void classGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) { switch(m_Mode) { case mode_zoomin: // надо сделать зум например break; case ... ... } } Так вот, сам вопрос, scale и rotate, они ж принадлежат объекту класса classGraphicsView. Как мне их вызвать из одного из этих case? Я так полагаю, либо я сделал неправильно архитектуру взаимодействия классов, либо как-то нужно сделать слоты и сигналы, тока не оч. пойму как это лучше сделать :\ Название: Re: QGraphicsView/Scene Отправлено: Rcus от Январь 13, 2009, 10:40 Я бы это реализовал как перехватчик событий представления, который имеет слот для смены состояния. А внутри класса делегировать полномочия по обработке событий через функциональные указатели/композицию объектов
Название: Re: QGraphicsView/Scene Отправлено: Rcus от Январь 13, 2009, 14:11 /*hdr*/
Код /*src*/ Код
Через функциональные указатели конечно просто, но для чего-то серьезного непригодно, а идея композиции уже была указана в сообщении BRE. Название: Re: QGraphicsView/Scene Отправлено: pethead от Октябрь 29, 2010, 06:23 не подскажете код как прорисовать в QGraphicsView\Scene фоновую картинку карты? читал читал но че то не все понял. сделал отрисовку в методе QGraphicsView::drawBackground, карта рисуется и масштабируется, но при сдвижке по скроллам карта портится (пошла полосами)
Код
я делал карту через браш: view->setBackgroundBrush(QPixmap("C:/RUSMAP1.bmp")); в принципе устраивает, и работает прекрасно, правда если карта маленькая то она размножается как tile :) так бы сделать только через метод drawBackground но не получается что то ... **решено: сделал так: Код
Название: Re: QGraphicsView/Scene Отправлено: GreatSnake от Октябрь 29, 2010, 12:31 Цитировать я делал карту через браш: Ни в коем случае не доверяйте это делать Qt. Особенно если используете трансформации.view->setBackgroundBrush(QPixmap("C:/RUSMAP1.bmp")); Вот вариант. Работает с очень большими изображениями с любыми трансформациями: Код QImage *bg_image_; - предварительно загруженная картинка Цитировать void cene::drawBackground(QPainter *painter, const QRectF &rect) Очень неоптимальный вариант.{ int w=img.width(); int h=img.height(); QRectF r; r.setRect(0,0,w,h); painter->drawImage(r,img); } При любом изменении вьюпорта будет перерисовываться вся картинка. А если захотите использовать масштабирование, то Qt каждый раз будет масштабировать ВСЮ(!) картинку. Название: Re: QGraphicsView/Scene Отправлено: pethead от Октябрь 29, 2010, 12:46 что такое "изменение вьюпорта"?
так а мне и надо чтоб картинка (карта) тоже масштабировалась. попробую ваш код - посмотрю что он делает.... посмотрел... при изменении масштаба меняются пропрции карты, а при масштабе 100% она не возвращается в 1:1. какие то странности., меня устраивает мой неоптимальный код. :) спасибо за ответы. Название: Re: QGraphicsView/Scene Отправлено: GreatSnake от Октябрь 29, 2010, 13:18 Цитировать посмотрел... при изменении масштаба меняются пропрции карты, а при масштабе 100% она не возвращается в 1:1. Значит как-то не так масштабируетеЦитировать какие то странности., меня устраивает мой неоптимальный код. Улыбающийся Ну-ну)спасибо за ответы. Название: Re: QGraphicsView/Scene Отправлено: pethead от Октябрь 29, 2010, 13:29 как не так?
Код: double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100.0; вот приложил скрины. w* это мой код делает, с* это ваш (на 150% он вообще ипортил карту), а у меня все в соответствии с масштабом. http://narod.ru/disk/26716931000/PIC.ZIP.html Название: Re: QGraphicsView/Scene Отправлено: GreatSnake от Октябрь 29, 2010, 15:00 да вроде так.
Вообщем как хочешь, но имей в виду, что Qt в твоём варианте будет постоянно скейлить твою картинку. И чем больше она будет, тем больше будет нагрузка. Судя по твоим скринам и скроллбарам на них, у тебя какие-то проблемы с геометрией сцены. Название: Re: QGraphicsView/Scene Отправлено: ufna от Октябрь 29, 2010, 15:15 Идея Великого Змея нормальна - скейлить только видимую часть - это убыстряет отрисовку когда речь идет о скейле в большую сторону - в минус то Кутэ скейлить очень быстро. А вот реализация судя по скринам немного хромает.
Название: Re: QGraphicsView/Scene Отправлено: pethead от Октябрь 29, 2010, 15:23 ну не знаю, но с вашим кодом картинка вообще кривая. скриншоты выложил. может ваш код у вас работает и скейлит не постоянно, а по нужде, но у меня вот он так как то заработал (судя по скринам).
на моем варианте загрузил карту, поскалировал, подвигал загрузка процессора не превышает 25% в моменты скалинга, передвижки, а так вообще не занимает проц. Название: Re: QGraphicsView/Scene Отправлено: GreatSnake от Октябрь 29, 2010, 15:35 2 ufna
Идея давным-давно внедрена и замечательно работает :) Единственный момент, если идёт движение элементов, то могут быть нестыковки на границах в пределах 1pix из-за погрешности вычислений геометрии exposed области. Единственное как удалось побороть - выставить у вью setCacheMode( CacheBackground ); 2 pethead Цитировать в смысле "будет скейлить"? так мне и надо чтобы он ее скейлил. :) или что не так то? по вашему он должен ее скуйлить, но не постоянно? а когда? Чтобы отрисовать дырку допустим 4х4 Qt будет масштабировать всю твою картинкуЦитировать загрузил карту, поскалировал, подвигал загрузка процессора не первышает 25% в моменты скалинга, передвижки, а так вообще не занимает проц. Вот когда подложка будет не 800х600, а 5000x5000 ты это сразу заметишь ;)Цитировать ну не знаю, но с вашим кодом картинка вообще кривая А drawBackground() переопределяется в наследнике QGraphicsView или QGraphicsScene?И почему на скринах такие странные скроллбары? Название: Re: QGraphicsView/Scene Отправлено: ufna от Октябрь 29, 2010, 15:48 Цитировать Идея давным-давно внедрена и замечательно работает Единственный момент, если идёт движение элементов, то могут быть нестыковки на границах в пределах 1pix из-за погрешности вычислений геометрии exposed области. Единственное как удалось побороть - выставить у вью setCacheMode( CacheBackground ); а, ну вполне может быть, я судил по скринам выше, не более чем. Суть то правильная, хотя на мой взгляд можно еще оптимизировать :) 1 пиксель тут это да, знаю, понимаю ) Название: Re: QGraphicsView/Scene Отправлено: GreatSnake от Октябрь 29, 2010, 15:51 Цитировать Суть то правильная, хотя на мой взгляд можно еще оптимизировать Ну дык, делись идеями ;)Название: Re: QGraphicsView/Scene Отправлено: pethead от Октябрь 30, 2010, 13:30 Цитировать А drawBackground() переопределяется в наследнике QGraphicsView или QGraphicsScene? QGraphicsView.И почему на скринах такие странные скроллбары? что значит странные? подвинутые. Название: Re: QGraphicsView/Scene Отправлено: mal от Ноябрь 07, 2010, 14:50 Возможно продублирую ответ Rcus'а.
Сделай две переменные под масштаб и угол разворота. В соответствующих слотах/эвентах мышки меняй значения этим параметрам и зови функцию устанавливающую вьхе матрицу откуда захочешь. Типа Код: qreal scale; |