Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: deaks от Март 09, 2011, 16:47



Название: Рисование в QGraphicScene
Отправлено: deaks от Март 09, 2011, 16:47
Всем привет!

Ребята, подскажите, что я делаю неправильно -

В конструкторе главного окна делаю так
1) Создаю сцену
Код
C++ (Qt)
   QGraphicsScene scene = new QGraphicsScene(this);
   scene.setSceneRect(-300, -300, 300, 300);
   scene.setItemIndexMethod(QGraphicsScene::NoIndex);
2) Добавляю к ней итемы, унаследованные от QGraphicsItem
Код
C++ (Qt)
   for (int i = 0; i < 3; ++i) {
       Target *target= new Target;
       scene.addItem(target);
   }
3) Подключаю сцену к представлению(QGraphicsView), созданному через дизайнер
Код
C++ (Qt)
   ui->grvMain->setScene(&scene);
 

Но в итоге ничего не отображается. Хотя итемы инициализируются начальными координатами


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 09, 2011, 16:56
Что такое Target?


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 09, 2011, 17:00
класс унаследованный от QGraphicsItem. Пока реализует только рисование объекта.


Название: Re: Рисование в QGraphicScene
Отправлено: Kolobok от Март 09, 2011, 17:02
Оно и компилироваться не должно.


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 09, 2011, 17:02
Цитата: deaks
класс унаследованный от QGraphicsItem. Пока реализует только рисование объекта.
Ну и как мы догадаемся как он это рисование реализует и какие ещё методы базового были перегружены?
Код давай.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 09, 2011, 17:07
Все рисуется в переопределенном методе QGraphicsView::paint()
 
Код
C++ (Qt)
  painter->setBrush(color);
   painter->drawEllipse(-20, -20, 20, 20);


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 09, 2011, 17:10
Показывай boundingRect() и чем не устроил QGraphicsEllipseItem?


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 09, 2011, 17:15
Код
C++ (Qt)
QRectF Target::boundingRect() const
{
   qreal adjust = 0.5;
   return QRectF(-18 - adjust, -22 - adjust,
                 36 + adjust, 60 + adjust);
}

Я только для пример привел рисование эллипса. В дальнейшем в этом итеме будут гораздо сложные объекты


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 09, 2011, 18:20
решил залить фоном QGraphicsView
Код
C++ (Qt)
   ui->grvMain->setBackgroundBrush(QPixmap(":/img/map.jpg"));
 
но результат нулевой. ничего не изменилось. как это понимать?)


Название: Re: Рисование в QGraphicScene
Отправлено: meego_man от Март 09, 2011, 18:45
стандартные items не пробовали добавить, просто чтобы определить подключена ли сцена к view или нет?


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 09, 2011, 18:51
пробовал, не рисуется. я как раз и подозревал, что сцена не подключена к виду, для этого выложил ход моих действий=)


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 09, 2011, 19:25
ребят, подскажите пожалуйста) совсем не пойму где мог накосячить. делал как написано в ассистанте:
создал объект сцену, создал итем, добавил к сцене, добавил сцену к вью.


Название: Re: Рисование в QGraphicScene
Отправлено: alexman от Март 09, 2011, 19:59
Попробуй вызвать void QGraphicsView::fitInView ( const QRectF & rect, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio ) с нужными параметрами.


Название: Re: Рисование в QGraphicScene
Отправлено: merke от Март 10, 2011, 11:12
Код:
 QGraphicsScene scene = new QGraphicsScene(this);
замени на
Код:
 QGraphicsScene *scene = new QGraphicsScene(this);

Пример рисования эллипса:
Код
C++ (Qt)
   QGraphicsEllipseItem *pkrug = new QGraphicsEllipseItem(0, scene);
 
   pkrug->setPen(QPen(Qt::black));
   pkrug->setBrush(QBrush(Qt::yellow));
   pkrug->setRect(QRectF(-30,-30,120,80));
   pkrug->setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsSelectable);


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 10, 2011, 12:58
Вот работающий пример:
Код
C++ (Qt)
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
 
class CircleItem : public QGraphicsItem
{
public:
CircleItem( qreal radius, QGraphicsItem* parent = 0 )
: QGraphicsItem( parent )
, radius_( radius ) {}
virtual ~CircleItem() {}
void paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0 )
{
painter->drawEllipse( QRectF( -radius_ / 2, -radius_ / 2, radius_, radius_ ) );
}
QRectF boundingRect() const
{
return QRectF( -radius_ / 2, -radius_ / 2, radius_, radius_ );
}
public:
qreal radius_;
};
 
int main( int argc, char** argv )
{
QApplication app( argc, argv );
QGraphicsView gv;
QGraphicsScene scene( -150, -150, 300, 300 );
 
gv.setScene( &scene );
gv.setRenderHint( QPainter::Antialiasing );
 
for( qreal r = 20; r < 300; r += 10 )
scene.addItem( new CircleItem( r ) );
 
gv.show();
return app.exec();
}
 

И похоже, все проблемы из-за
Код
C++ (Qt)
scene.setSceneRect( -300, -300, 300, 300 );
Из-за смещения сцены на её размеры, получается вся отрисовка делается за пределами вьюпорта.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 10, 2011, 16:53
Большое спасибо, разобрался и теперь все рисуется как надо! ;)

Хотелось бы еще узнать следующее -
мне необходимо отображать на карте(QGraphicsScene) двигающиеся объекты(QGraphicsItem, которые являются QPixmap из ресурсов). Перерисовка происходит каждые 10 мсек, путем установки ->setPos для каждого объекта.

В результате во-первых сильно искажаются картинки, помещенные в QPixmap; во-вторых перерисовка идет крайне медленно и все тормозит. Необходимо как-то указывать точные области перерисовки? да и вообще правильно ли я делаю?


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 10, 2011, 16:59
Показывай paint().


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 10, 2011, 17:03
вот
Код
C++ (Qt)
    QPixmap pixmap(":/img/res__su30.png");
    painter->drawPixmap(0,0, pixmap);


Название: Re: Рисование в QGraphicScene
Отправлено: Авварон от Март 10, 2011, 17:07
пиксмапу в пееменную сохрани... каждый раз из файла читать кто угодно тормозить начнет


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 10, 2011, 17:14
Цитировать
QPixmap pixmap(":/img/res__su30.png");
Да уж... Мог бы и сам сразу догадаться...


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 10, 2011, 17:28
согласен!
добавил в конструкторе класса метод load, но проблема все равно не решилась.

объекты перестали двигаться. перерисовка выполняется только при движении скроллами или при щелчке мышкой рядом. неверно заданы зоны отрисовки? boundingRect задал прямоугольником 200х200


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 10, 2011, 17:32
Цитировать
неверно заданы зоны отрисовки?
Именно
Цитировать
boundingRect задал прямоугольником 200х200
А почему не задавать конкретные от QPixmap::rect() ?


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 10, 2011, 17:48
Цитата: GreatSnake
QPixmap::rect()

вот уж спасибо, не знал)!!!все отлично!

посоветуйте еще, как все-таки быть с тем, что при выполнении ->setRotation картинка искажается?


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 10, 2011, 18:00
Цитировать
посоветуйте еще, как все-таки быть с тем, что при выполнении ->setRotation картинка искажается?
Как искажается-то? И надо иметь в виду, что при повороте на угол не кратный 90 искажения будут по-любому.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 10, 2011, 18:15
а ну да, все верно.я как понимаю, чтобы искажения были менее заметными необходимо брать картинку более высоко разрешения?


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 10, 2011, 18:22
Да. Ну и поиграться со сглаживанием.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 11, 2011, 12:29
устанавливал антиалайзинг для QPainter и для QGraphicsView, но картинка все равно не сглаживается.
непонятно как это сделать именно для QPixmap, хотя видимо этой возможности совсем нет


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 15, 2011, 19:20
товарищи, подскажите верно ли делаю -

необходимо нарисовать самолет и маршрут его движения. все соответственно в 2d

для этого создал объект-самолет, унаследованный от QGraphicsItem и включающий объект-маршрут, также унаследованный от QGraphicsItem

объект-маршрут состоит из массива координат и пополняется с определенным временным шагом.

когда создаю объект-самолет, то его и его маршрут добавляю к сцене. соответственно у каждого из объектов реализованы
->boundingRect и ->paint . маршрут рисую с помощью ->drawPath


Название: Re: Рисование в QGraphicScene
Отправлено: ufna от Март 15, 2011, 20:53
ну там еще есть куча флагов для QGV + флаг SmoothPixmapTransform никто не отменял (а именно он работает для поворотов)


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 15, 2011, 22:01
с изображением уже разобрался) но всеравно спасибо!

сейчас больше всего интересует как маршрут отображать


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 16, 2011, 11:08
Цитировать
сейчас больше всего интересует как маршрут отображать
Всё зависит от частоты обновления траектории движения самолёта и длины самой траектории.
Можно в свойствах элемента самолёта держать список из QGraphicsLineItem и просто добавлять в начало этого списка новый QGraphicsLineItem.
Если "количество шагов траектории" лимитировано, то лишние просто удаляем с конца списка. Получится такая ползучая змея)
Если всё координаты держать в одном элементе, то может сильно проседать рендеринг, т.к. каждый раз придётся перерисовывать весь хвост, boundingRect() которого может быть довольно большим.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 16, 2011, 11:32
логично!!!

сейчас как раз и наблюдаю проблемы с ->boundingRect.
Попробую сделать с массивом линий!огромное спасибо


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 10:33
Ситуация такая:

при добавлении нового объекта происходит "захват" его. то есть где бы он не появился он всегда становится в центре экрана.
то есть он стоит в центре QGraphicsView

хочется убрать это. пробовал убирать фокус со сцены, но ничего не помогает. как быть?)


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 10:58
Цитировать
то есть где бы он не появился он всегда становится в центре экрана.
А как делается позиционирование элемента? Через QGraphicsItem::setPos()?
По умолчанию все элементы позиционируются в 0,0. А судя по тому, что сцена отцентрирована, элементы будут в центре.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 11:18
да, через ->setPos
А когда тогда сделать относительное позиционирование?


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 11:21
Цитировать
А когда тогда сделать относительное позиционирование?
Можно как-нибудь по-русски и более развёрнуто задавать вопросы?


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 12:04
Извините  ;)

В общем так, у меня есть бекграунд(радар) на фоне которого должны перемещаться объекты. то есть этот радар должен быть всегда в центре виджета.

а сейчас получается - добавляю объект и он становится в центре виджета


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 12:16
(http://s60.radikal.ru/i169/1103/92/7e51a56dbe8d.jpg) - вот как сейчас это дело выглядит


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 12:24
Коли начальные координаты сцены в центре, то и позиционирование элементов должно делаться с учётом этого.
Т.е. если нужно сдвинуть самолёт в самый левый верхий угол, то нужно его двигать через
setPos( -sceneRect().width() / 2, -sceneRect().height() / 2 )


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 12:35
это само-собой, но суть в другом - видите на картинке самолет в центре виджета. а мне необходимо чтобы в центре виджета всегда был радар. получается что сцена закреплена


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 12:36
одно из решений - постоянно перерисовывать радар в центре виджета. но это конечно же неверно


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 12:41
Цитировать
мне необходимо чтобы в центре виджета всегда был радар.
Помести радар в начало сцены ( в 0,0 ) и рисуй эллипсы как я показывал здесь (http://www.prog.org.ru/index.php?topic=17121.msg114848#msg114848).

Цитировать
получается что сцена закреплена
Что значит "сцена закреплена"? Откуда такое понятие и такой вывод?


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 14:32
а если я рисую радар фоном(не хочу заводить отдельный итем) в переопределенном методе QGraphicsView::drawBackground как мне его всегда перемещать в центр сцены?


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 15:13
Цитировать
а если я рисую радар фоном(не хочу заводить отдельный итем) в переопределенном методе QGraphicsView::drawBackground как мне его всегда перемещать в центр сцены?
Painter в drawBackground() уже перемещён в начальную координату. Это нужно учитывать, т.к. вся отрисовка делается относительно позиции painter-a.
В твоём случае позиция будет QPointF( sceneRect().width() / 2, sceneRect().height() / 2 )


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 15:15
так что, радар обязательно делать отдельным итемом?


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 15:26
Цитировать
так что, радар обязательно делать отдельным итемом?
Почему ???


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 15:32
то есть чтобы окружность всегда рисовалась в центре виджета, надо делать так -
Код
C++ (Qt)
void TargetsView::drawBackground(QPainter *painter, const QRectF &rect)
{
   QPointF center(sceneRect().width() / 2, sceneRect().height() / 2);
   painter->drawEllipse(center, 90, 90);
}


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 15:53
Цитировать
то есть чтобы окружность всегда рисовалась в центре виджета, надо делать так -
Не так, а вот так:
Код
C++ (Qt)
void TargetsView::drawBackground(QPainter *painter, const QRectF &rect)
{
   painter->drawEllipse(QPointF( 0, 0 ), -45, -45);
}

Ещё раз читай мой предпоследний пост (http://www.prog.org.ru/index.php?topic=17121.msg115538#msg115538).
А вообще ассистент рулит)


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 16:12
а понял))
то есть пейнтер надо инициализировать (->translate)координатой центра сцены во время каждого вызова метода ->drawBackground.

Все хорошо. вижу что на 1ом шаге появляется правильная картинка, но затем ничего не рисуется((


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 16:15
Цитировать
а понял))
то есть пейнтер надо инициализировать (->translate)координатой центра сцены во время каждого вызова метода ->drawBackground.
Ничего ты не понял(
Читай ещё раз:
Цитировать
Painter в drawBackground() уже перемещён в начальную координату. Это нужно учитывать, т.к. вся отрисовка делается относительно позиции painter-a.
В твоём случае позиция будет QPointF( sceneRect().width() / 2, sceneRect().height() / 2 )
т.е. "курсор" painter-a уже стоит в центре.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 16:35
не понимаю  :-\ я в замешательстве

я ведь сам не вызываю drawBackground, как тогда задать эту позицию, про которую вы говорите :(((





Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 16:40
Цитировать
я ведь сам напрямую не вызываю drawBackground, как тогда задать эту позицию, про которую вы говорите
Да не надо ничего задавать. Painter уже стоит в центре. Все координаты должны быть относительные.
Ты что, вообще не читаешь, что тебе пишут ???
Для кого я писал сей код?
Код
C++ (Qt)
void TargetsView::drawBackground(QPainter *painter, const QRectF &rect)
{
   painter->drawEllipse(QPointF( 0, 0 ), -45, -45);
}


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 16:42
Ещё раз внимательно перечитай нашу переписку.


Название: Re: Рисование в QGraphicScene
Отправлено: deaks от Март 17, 2011, 16:56
видимо я не до конца принимаю принципа painter'a(связь между логическими и физическими координатами). буду разбираться)


Название: Re: Рисование в QGraphicScene
Отправлено: GreatSnake от Март 17, 2011, 17:02
Ещё раз.
Установив начало координат сцены в центре, ты сдвинул логические координаты пайнтера в центр.
А пайнтер при отрисовке использует именно логические координаты.