PDA

View Full Version : elastic QGraphicsItem (layout problem)



petar
11th November 2009, 14:34
Hy

I need a elastic layout so that when you stretch the mainwindow all items in it also stretch.

I have:

1) QMainWindow
2) GraphicsView
3) GraphicsItem on the Scene


Currently i have a grid layout added to my class.
My GraphicsView i set to expanding in the designer so that's good. But i have a QGraphicsItem circle that does not expanding together with his parent.

What i need is when you make window smaller, item also smaller. When you make window bigger item also bigger. How can i acomplish this? I'm searching and reading some hour or so and can't find it.

I'm not sure what i'm looking for, but i thought that something like this in the constructor i need:

pseudo-code:
this_constructed_object->stretch_with_parent_QGraphicsView

i don't really know...but i think that i need something like that in the constructor of my class:


CircleItem::CircleItem(QGraphicsItem *parent)
: QGraphicsItem(parent)

yogeshgokul
11th November 2009, 14:40
It will not be solved using a custom layout.
You may need to subclass QGraphicsView and override its resizeEvent(). In that, you need to zoom/scale the view so each item will be scaled respectively.

petar
11th November 2009, 14:51
Thanks, i understand what you'r saying, but is there a tutorial covering something similair maybe?

scascio
11th November 2009, 14:51
Hi,

I dont think that your problem is related to the constructor of your item.

In fact, you want a no conventionnal display of your QGraphicsView. Remember that is only a view of a QGraphicsScene.

So, what do you want to do exactly? When your view is resized, do you changes the positions and size of your items in the scene? Or you just want that the scene rendering will stretch the size of the view?
Not quite same needs, isn't it?

And what about moving in the scene? Don't you need that features?

Anyway, have a look at QGraphicsView::transform and QGraphicsView::scale
Dont forget, if you scale the view according to its rect size, to reset the transformation matrix because scale() scales the view form current matrix.

I hope I was helpful.

yogeshgokul
11th November 2009, 14:51
Please see this:

#include <QApplication>
#include <QDialog>
#include <QLayout>
#include <QGraphicsView>

class MyView:public QGraphicsView
{
public:
MyView(QWidget *parent = 0):QGraphicsView(parent)
{}
protected:
void resizeEvent(QResizeEvent * evt)
{
this->scale(x,y);//DO SOME WORK HERE
QGraphicsView::resizeEvent(evt);
}
};


int main(int argc, char **argv)
{
QApplication app(argc, argv);
QDialog dlg;
QVBoxLayout *vl=new QVBoxLayout(&dlg);
QGraphicsScene sc;
MyView mv(&dlg);
mv.setScene(&sc);
sc.addRect(10,10,200,200);
vl->addWidget(&mv);
dlg.show();
return app.exec();
}

You just need to calculate the scaling factor depending upon the current size of gv.
Pass that scaling factor in scale function of gv in resizeEvent.

petar
11th November 2009, 15:03
@Scasio:

http://lookpic.com/i/395/bGQxNt0B.jpeg (http://lookpic.com/i/395/bGQxNt0B.jpeg)

...

http://lookpic.com/i/856/NcrNsyzh.jpeg (http://lookpic.com/i/856/NcrNsyzh.jpeg)


Btw.

Yes, thx for the info but i haven't understood everything. I just need a simple way to resize items accordingly to the window (parent)

yogeshgokul
11th November 2009, 15:08
Have you tried my way ?

petar
11th November 2009, 15:26
You just need to calculate the scaling factor depending upon the current size of gv.
Pass that scaling factor in scale function of gv in resizeEvent.


Thanks yogeshgokul i will do some simple examples to figure it out.
It's different because in my app i have different setup.

here i go:



//Program entry point: instancing object of RuletV1 class
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
RuletV1 w;
w.show();
return a.exec();
}



//RuletV1.cpp
RuletV1::RuletV1(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags) {

ui.setupUi(this);
QGraphicsScene *scena = new QGraphicsScene();
ui.graphicsView->setScene(scena);
m_elipsa = new CircleItem();
scena->addItem(m_elipsa);

} RuletV1::~RuletV1(){}



//CirceItem.cpp
CircleItem::CircleItem(QGraphicsItem *parent)
: QGraphicsItem(parent) {}
//destructor
CircleItem::~CircleItem() {}

QRectF CircleItem::boundingRect() const { return QRectF(0,0,100,100); }

void CircleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
painter->setRenderHint(QPainter::Antialiasing);
painter->drawLine(0,50, 100, 50);
painter->drawLine(50, 0, 50, 100);
painter->drawEllipse(0, 0, 100, 100);
}


If i understand then you have also GraphicsView but not like me, you make yourself a class that inherits QGraphicsView, you named it MyView. And in that class you override a method called resizeEvent.

The rest i understand...i need to study that resizeEvent method and how to calculate scaling. Thx

petar
11th November 2009, 15:32
Have you tried my way ?

i'm trying -> will post result later

scascio
11th November 2009, 18:12
You only need to compute the right scale factor, according to the size of the widget,.

try something like this :


void YourGraphicsView::resizeEvent ( QResizeEvent * event ) {

QGraphicsView::resizeEvent(event);

const QSize& oldSize = event->oldSize();
const QSize& newSize = event->size();

//be aware of integer division and division by zero
double scaleFactorX = (oldSize.width ()>0) ? ((double)newSize.width())/oldSize.width ():1;
double scaleFactorY = (oldSize.height()>0) ?((double)newSize.height())/oldSize.height():1;

//sclae the view
scale(scaleFactorX, scaleFactorY);
}

But I am not sure that the behaviour will be correct for all cases.