PDA

View Full Version : QGraphicsScene geometric centre



Nadia
2nd September 2009, 12:17
Hi, all


Understanding the coordinates concepts for QGraphicsScene is quite hart to me :(.

Readin documentation I can clear understand QGraphicsView and Items coordinate but not scene. Now I write code not setting sceneRect and boundingRect for QGraphicsItem couse if I set them everething go wrong.


What I missunderstand is where is geometric centre of QGraphicsScene regarding QGraphicsView (widget)?:confused:

Thank you very much in advance.

wysota
2nd September 2009, 12:36
The view can display any region of the scene so there is no constant place for the centre of the scene regarding the view. You can use the family of mapTo*() methods of different objects to move between coordinate spaces.

Nadia
2nd September 2009, 15:12
If view can show any region of the scene which one it shows by default and what the sceneRect property mean? We should specify х, y, width and heigh for sceneRect. So setting the point (x,y) I should understand where it will be placed.


:confused: :confused:

wysota
2nd September 2009, 16:34
As far as I remember by default (0,0) coordinates of the scene are in (0,0) coordinates of the viewport unless the scene is smaller than the viewport - in that case the scene is centred in the viewport.

Nadia
3rd September 2009, 08:43
It does not look so. Maybe small example . I have scene, view and item as hare





#include "plot.h"
#include "chart.h"
#include <QPainter>
#include <QColor>
#include <QHBoxLayout>
#include <QMenuBar>
#include <QPushButton>
#include <QDebug>
#include <QDockWidget>

//just in shoret do not post .h file Plot inherits QMainWindow
Plot::Plot()
{
exitAction = new QAction(tr("E&xit"), this);

fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(exitAction);

scene = new PlotScene(QRectF());//if I set any value here I my plot will be pained outsie view


scene->setBackgroundBrush(QColor(Qt::green));
scene->addItem(new chart());//view call paint to do all work

view = new PlotView();
//view->setFixedSize(500,500);
view->setScene(scene);
//view->setBackgroundBrush(QColor(Qt::red));
setCentralWidget(view);

//add docWidget
QString s("Dock Widget");
QDockWidget *dockWidget = new QDockWidget(s);
dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea |
Qt::RightDockWidgetArea);

addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
QPushButton* tbutton = new QPushButton("Clear");
dockWidget->setWidget(tbutton);
//dockWidget->

//
connect( tbutton, SIGNAL(clicked()), scene, SLOT(clearPlot()) );

}
//-----------------------------------------------------------
#include "chart.h"
#include <QPainter>
#include <QWidget>
#include <QPolygonF>
#include <QStyleOptionGraphicsItem>
#include <QDebug>
#include "plot.h"
#include <math.h>


//chart inherits QGraphicsItem
chart::chart()
{
}

void chart::draw(QPainter *painter, QWidget *widget)
{

painter->drawLine(0,widget->height(), 0, 0-(widget->height()/2));
painter->drawLine(0-(widget->width()/2),0, (widget->width()/2), 0);

int step = 20;
int w = 5;
//draw y markers
for(int i =0; i<(widget->height()*2); i=i+step)
{
painter->drawLine(-w,widget->height()-i, w, widget->height()-i);
}

//draw x marker
for(int i =4; i<(widget->width()*2); i=i+step)
{
painter->drawLine(widget->width()-i, w, widget->width()-i, -w);
}
//draw sin()
QPolygonF pol;
for (double i=0; i<90; i=i+0.001)
{
pol.append(QPointF((i*60) - (widget->width()+155),sin(i)*100));
}

painter->drawPolyline(pol);

}
void chart::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{

// int side = qMin(widget->width(), widget->height());
QColor color(255,255,255);
QPen pen(color,1.5);
pen.setColor(color);
painter->setPen(pen);


draw(painter, widget);

qDebug() <<"boundingRect ="<<this->boundingRect();

//seems depend on main window geometry QRect(0,0 798x576)-2,-4
//The viewport represents the physical coordinates specifying an arbitrary rectangle.
qDebug() << "Painter viewport="<< painter->viewport();

//By default the logical and physical coordinate systems coincide,
//and are equivalent to the paint device's rectangle.
qDebug() << "Painter window = "<< painter->window();

//scene
//Returns the item's position in scene coordinates
qDebug() << "scene coordinates="<< this->scenePos();
}

wysota
3rd September 2009, 09:16
The code is incomplete. What is the boundingRect of the item? Furthermore the scene size is null thus the scene takes the dimensions of the bounding rect of all its items so it's hard to deduce anything from this code.

Also are you sure you actually want to use graphics view for something like that? If you make the chart size dependent on the widget size, it is likely graphics view will not do you much good.

Nadia
3rd September 2009, 10:14
The problem is then I set the boundingRect of the item the chart is painted outside the view.

Why view do not much this aim as far as I know "View coordinates are the coordinates of the widget."(from QT doc)



#ifndef CHART_H
#define CHART_H

#include <QGraphicsItem>

class chart : public QGraphicsItem
{
public:
chart();

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const
{
//qreal penWidth = 1;
return QRectF();
}

private:
//for internal use only shoul be called by paint
void draw(QPainter *painter, QWidget *widget);


};

#endif // CHART_H

wysota
3rd September 2009, 10:36
The bounding rect you return needs to be valid. If it's not, your item will not be drawn properly. You need to return a bounding rect that will determine the local coordinate space for the object. For example you can return QRectF(0,0,600,400) and then in the paint routine only draw within those coordinates. You can move your item around by using QGraphicsItem::setPos() and make it bigger or smaller (relative to the scene) using QGraphicsItem::scale(). You can also make the whole scene bigger or smaller by scaling the view.

Nadia
3rd September 2009, 11:26
I know that I should set vaild bounding rect but when I set


QRectF boundingRect() const
{
//qreal penWidth = 1;
return QRectF(-800, -600, 800, 600);
}


It draw some where outside .....

wysota
3rd September 2009, 13:49
Did you adjust your paint() accordingly?

Nadia
3rd September 2009, 14:03
It seems yes , e.g. lines.




painter->drawLine(0,widget->height(), 0, 0-(widget->height()/2));
painter->drawLine(0-(widget->width()/2),0, (widget->width()/2), 0);






Plot p;
//set (x,y) w and h relative to screen
p.setGeometry(100, 100, 800, 600);

p.show();
but result is that they are painted somewhere around.....

wysota
3rd September 2009, 14:17
Well... this is not enough :)
Get rid of this method:

void chart::draw(QPainter *painter, QWidget *widget)
Don't access the widget anywhere.

Use the options object in paint() to get information about how you should paint your item.

Paint the item in absolute (-800, -600) to (0,0) coordinates.

BTW. didn't you mean your bounding rect to return (-800, -600, 1600, 1200)?

Nadia
3rd September 2009, 14:32
Ok I just added chart::draw for future extension:p. Without it it work in the same way.

:pBUT if I set bounding rect to return (-800, -600, 1600, 1200) it is centred in nice way......:confused: why ? and I get scroll around the scene.....

wysota
3rd September 2009, 14:38
I don't understand the question.