Russian Qt Forum
Ноябрь 02, 2024, 10:16 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: QGraphicsView/Scene  (Прочитано 22398 раз)
pethead
Гость
« Ответ #15 : Октябрь 29, 2010, 06:23 »

не подскажете код как прорисовать в QGraphicsView\Scene фоновую картинку карты? читал читал но че то не все понял. сделал отрисовку в методе QGraphicsView::drawBackground, карта рисуется и масштабируется, но при сдвижке по скроллам карта портится (пошла полосами)


Код
C++ (Qt)
QPixmap map;
 
//так же делаю
view->setDragMode(QGraphicsView::ScrollHandDrag);
view->centerOn(0,0);// карта рисутется от левого верхнего угла сцены - все ок.
//но если подвигать скроллы карта рисуется все время угла видимой области, а не от угла 0,0 сцены.
//(делал и Scene::drawBackground)
 
NetView::NetView(QGraphicsScene *scene, QWidget *parent)
   : QGraphicsView(scene, parent)
{
QString name = "C:/MAP1.bmp";
map.load(name);
}
 
void NetView::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->drawPixmap(rect.left(),rect.top(),map);
}
 

я делал карту через браш:
view->setBackgroundBrush(QPixmap("C:/RUSMAP1.bmp"));
в принципе устраивает, и работает прекрасно, правда если карта маленькая то она размножается как tile Улыбающийся
так бы сделать только через метод drawBackground но не получается что то ...

**решено:
сделал так:

Код
C++ (Qt)
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);
}
« Последнее редактирование: Октябрь 29, 2010, 12:22 от pethead » Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #16 : Октябрь 29, 2010, 12:31 »

Цитировать
я делал карту через браш:
view->setBackgroundBrush(QPixmap("C:/RUSMAP1.bmp"));
Ни в коем случае не доверяйте это делать Qt. Особенно если используете трансформации.

Вот вариант. Работает с очень большими изображениями с любыми трансформациями:
Код
C++ (Qt)
void MyScene::drawBackground( QPainter* p, const QRectF& clip )
{
if( !bg_image_ )
{
QGraphicsScene::drawBackground( p, clip );
return;
}
 
p->eraseRect( clip );
 
QMatrix wm( p->worldMatrix() );
 
if( wm.m11() != 1 &&
clip.intersects( bg_image_->rect() ) )
{
QImage img;
QRectF c( clip );
if( wm.m11() > 1 )
c.adjust( -1, -1, 1, 1 );
 
qreal cx = c.x();
qreal cy = c.y();
qreal cw = qMax( 16., c.width() );
qreal ch = qMax( 16., c.height() );
 
if( cx < 0 )
{
cw += cx;
cx = 0;
}
if( cy < 0 )
{
ch += cy;
cy = 0;
}
cw = qMin( cw, bg_image_->width() - cx );
ch = qMin( ch, bg_image_->height() - cy );
img = bg_image_->copy( QRectF( cx, cy, cw, ch ).toRect() );
cw = qRound( cw * wm.m11() );
ch = qRound( ch * wm.m11() );
img = img.scaled( (int) cw, (int) ch, Qt::IgnoreAspectRatio,
/*wm.m11() > .8 ? Qt::SmoothTransformation :*/ Qt::FastTransformation );
p->setWorldMatrix( QMatrix( 1, 0, 0, 1, wm.dx(), wm.dy() ) );
p->drawImage( QPointF( cx * wm.m11(), cy * wm.m11() ), img );
p->setWorldMatrix( wm );
} else
{
p->drawImage(
QPointF( clip.x(), clip.y() ),
*bg_image_,
QRectF( clip.x(), clip.y(),
qMin( clip.width(), qreal( bg_image_->width() ) ),
qMin( clip.height(), qreal( bg_image_->height() ) ) ) );
}
}
 
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 каждый раз будет масштабировать ВСЮ(!) картинку.
« Последнее редактирование: Ноябрь 26, 2010, 14:43 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
pethead
Гость
« Ответ #17 : Октябрь 29, 2010, 12:46 »

что такое "изменение вьюпорта"?
так а мне и надо чтоб картинка (карта) тоже масштабировалась.

попробую ваш код - посмотрю что он делает....
посмотрел... при изменении масштаба меняются пропрции карты, а при масштабе 100% она не возвращается в 1:1.
какие то странности., меня устраивает мой неоптимальный код. Улыбающийся
спасибо за ответы.
« Последнее редактирование: Октябрь 29, 2010, 12:56 от pethead » Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #18 : Октябрь 29, 2010, 13:18 »

Цитировать
посмотрел... при изменении масштаба меняются пропрции карты, а при масштабе 100% она не возвращается в 1:1.
Значит как-то не так масштабируете

Цитировать
какие то странности., меня устраивает мой неоптимальный код. Улыбающийся
спасибо за ответы.
Ну-ну)
Записан

Qt 5.11/4.8.7 (X11/Win)
pethead
Гость
« Ответ #19 : Октябрь 29, 2010, 13:29 »

как не так?

Код:
    double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100.0;
    QMatrix oldMatrix = view->matrix();
    view->resetMatrix();
    view->translate(oldMatrix.dx(), oldMatrix.dy());
    view->scale(newScale, newScale);


вот приложил скрины. w* это мой код делает, с* это ваш (на 150% он вообще ипортил карту), а у меня все в соответствии с масштабом.
http://narod.ru/disk/26716931000/PIC.ZIP.html
« Последнее редактирование: Октябрь 29, 2010, 13:41 от pethead » Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #20 : Октябрь 29, 2010, 15:00 »

да вроде так.
Вообщем как хочешь, но имей в виду, что Qt в твоём варианте будет постоянно скейлить твою картинку. И чем больше она будет, тем больше будет нагрузка.

Судя по твоим скринам и скроллбарам на них, у тебя какие-то проблемы с геометрией сцены.
« Последнее редактирование: Октябрь 29, 2010, 15:12 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
ufna
Гость
« Ответ #21 : Октябрь 29, 2010, 15:15 »

Идея Великого Змея нормальна - скейлить только видимую часть - это убыстряет отрисовку когда речь идет о скейле в большую сторону - в минус то Кутэ скейлить очень быстро. А вот реализация судя по скринам немного хромает.
Записан
pethead
Гость
« Ответ #22 : Октябрь 29, 2010, 15:23 »

ну не знаю, но с вашим кодом картинка вообще кривая. скриншоты выложил. может ваш код у вас работает и скейлит не постоянно, а по нужде, но у меня вот он так как то заработал (судя по скринам).
на моем варианте загрузил карту, поскалировал, подвигал загрузка процессора не превышает 25% в моменты скалинга, передвижки, а так вообще не занимает проц.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #23 : Октябрь 29, 2010, 15:35 »

2 ufna
Идея давным-давно внедрена и замечательно работает  Улыбающийся
Единственный момент, если идёт движение элементов, то могут быть нестыковки на границах в пределах 1pix из-за погрешности вычислений геометрии exposed области. Единственное как удалось побороть - выставить у вью setCacheMode( CacheBackground );

2 pethead
Цитировать
в смысле "будет скейлить"? так мне и надо чтобы он ее скейлил. Улыбающийся или что не так то? по вашему он должен ее скуйлить, но не постоянно? а когда?
Чтобы отрисовать дырку допустим 4х4 Qt будет масштабировать всю твою картинку

Цитировать
загрузил карту, поскалировал, подвигал загрузка процессора не первышает 25% в моменты скалинга, передвижки, а так вообще не занимает проц.
Вот когда подложка будет не 800х600, а 5000x5000 ты это сразу заметишь Подмигивающий

Цитировать
ну не знаю, но с вашим кодом картинка вообще кривая
А drawBackground() переопределяется в наследнике QGraphicsView или QGraphicsScene?
И почему на скринах такие странные скроллбары?
« Последнее редактирование: Октябрь 29, 2010, 15:43 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
ufna
Гость
« Ответ #24 : Октябрь 29, 2010, 15:48 »

Цитировать
Идея давным-давно внедрена и замечательно работает 
Единственный момент, если идёт движение элементов, то могут быть нестыковки на границах в пределах 1pix из-за погрешности вычислений геометрии exposed области. Единственное как удалось побороть - выставить у вью setCacheMode( CacheBackground );

а, ну вполне может быть, я судил по скринам выше, не более чем. Суть то правильная, хотя на мой взгляд можно еще оптимизировать Улыбающийся

1 пиксель тут это да, знаю, понимаю )
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #25 : Октябрь 29, 2010, 15:51 »

Цитировать
Суть то правильная, хотя на мой взгляд можно еще оптимизировать
Ну дык, делись идеями Подмигивающий
Записан

Qt 5.11/4.8.7 (X11/Win)
pethead
Гость
« Ответ #26 : Октябрь 30, 2010, 13:30 »

Цитировать
А drawBackground() переопределяется в наследнике QGraphicsView или QGraphicsScene?
И почему на скринах такие странные скроллбары?
QGraphicsView.
что значит странные? подвинутые.
Записан
mal
Гость
« Ответ #27 : Ноябрь 07, 2010, 14:50 »

Возможно продублирую ответ Rcus'а.
Сделай две переменные под масштаб и угол разворота.
В соответствующих слотах/эвентах мышки меняй значения этим параметрам и зови функцию устанавливающую вьхе матрицу откуда захочешь.
Типа
Код:
qreal scale;
int angle;
...
slot_scale()
{
   scale = ...
setupMatrix();
}
slot_rotate()
{
angle = ...
setupMatrix();
}

setupMatrix()
{
   QMatrix matrix;
   matrix.rotate(angle);
   matrix.scale(scale, scale);
   view->setMatrix(matrix);
}
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.117 секунд. Запросов: 23.