PDA

View Full Version : QGraphicsScene and View



bikonja
13th February 2015, 12:04
Hello guys, this is yet another topic about coordinates.
im making a tetris game and i'm having some trouble setting up the scene.
i'm aware of the documentation, but learning another library on my own is quite new to me, and im kind of lost in all those words.

consider the following code


myRect::myRect(QGraphicsItem *parent) : QGraphicsItem(parent)
{
setFlag(QGraphicsItem::ItemIsFocusable);
}

QRectF myRect::boundingRect() const
{
return QRectF(0,0,50,50);
}

void myRect::keyPressEvent(QKeyEvent *event)
{
switch( event->key())
{
case Qt::Key_Left:{
setPos(x()-10,y());
checkBounds();
break;
}
case Qt::Key_Right:{
setPos(x()+10,y());
checkBounds();
break;
}
case Qt::Key_Up:{
setPos(x(),y()-10);
checkBounds();
break;
}
case Qt::Key_Down:{
setPos(x(),y()+10);
checkBounds();
break;
}
}
update();
}

void myRect::checkBounds()
{
if (x() < 0)
{
setPos(0, y());
}
else if (x() + boundingRect().right() > scene()->width())
{
setPos(scene()->width() - boundingRect().width(), y());
}

if (y() < 0)
{
setPos(x(), 0);
}
else if ( y()+ boundingRect().bottom() > scene()->height())
{
setPos(x(), scene()->height() - boundingRect().height());
}
}

void myRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setBrush(Qt::yellow);
painter->drawRoundRect(0,0,50,50,5,5);
}


Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
scene = new QGraphicsScene();
ui->view->setScene(scene);
scene->setSceneRect(0,0,ui->view->frameSize().width(),
ui->view->frameSize().height());
rect = new myRect;
scene->addItem(rect);
rect->setPos(scene->width()/2,0);
rect->setFocus();

}

so my question(s) is this.

i'm under the impresion my scene should have the same dimensions and the view.
but when i add my item on the scene it aint possitioned in the middle.
can someone explain to me whats going on here?

also.

lets say i want to have 8 columns on my board and 16 rows for block movement.

so my I block could be placed 2 times horizontally rotated on the board, and 8 times vertically.

10955

excuse me for my paint skills.

can you help me out with setting that up?

wysota
13th February 2015, 15:49
The proper size for your scene is more likely ui->view->viewport()->size(). Just remember widgets get their size set only after they become visible for the first time. So you need to set the scene size when the view is visible, e.g. during the view's resizeEvent. Alternatively make your scene have fixed size and scale it to the view in resize event using scaleToFit().

bikonja
13th February 2015, 16:15
Hmm, well tbh that didn't help me much.

I used my designer to make the widget fixed size, and used the designer as well to create a QGraphicsview, which i also made fixed size.
So i wont have any resize events afaik.

for example my widget is 300x520,
and when i do
scene->setSceneRect(0,0,ui->view->frameSize().width(),ui->view->frameSize().height());

i have a feeling my scene aint identical to my view.

this game will be as blunt as possible, so i dont need any magic here.

can you just help me understand how to set up the board as i mentioned in the first post?

thx

wysota
13th February 2015, 17:24
I used my designer to make the widget fixed size, and used the designer as well to create a QGraphicsview, which i also made fixed size.
So i wont have any resize events afaik.
You will have at least one.


scene->setSceneRect(0,0,ui->view->frameSize().width(),ui->view->frameSize().height());
Because you ignored what I have written in my previous post. After construction the widget size is invalid. So it's frame size is likely invalid as well. You had checked it before writing this post, right?


can you just help me understand how to set up the board as i mentioned in the first post?

I have already done that.

bikonja
13th February 2015, 18:14
yeah, thx alot.

you didn't answer neither of my questions in a precise answer. you are quoting me documentaion which i mentioned i have problems reading with.

so no, you didnt allready explain it to me.

Added after 38 minutes:

also i can't find scaleToFit() anywhere.

wysota
13th February 2015, 21:34
yeah, thx alot.

you didn't answer neither of my questions in a precise answer. you are quoting me documentaion which i mentioned i have problems reading with.

so no, you didnt allready explain it to me.
Did you implement resizeEvent() for your view? Did you check the actual size of the scene?

I gave you a precise recipe what to do to make your code work (set the scene size to the size of the viewport from within a resize event). And I didn't quote any documentation, I was writing that post from my tablet while riding in a bus, quoting documentation in such conditions is not that comfortable.


Added after 38 minutes:

also i can't find scaleToFit() anywhere.

Sorry, that is fitInView(), I was writing the method name from the top of my head. I assumed that even if I mistyped the name, you'd find the right name anyway as it is the only method which has "fit" in its name.


#include <QtWidgets>

#define SCALETOFIT

class GraphicsView : public QGraphicsView {
public:
GraphicsView() : QGraphicsView() { item = 0; }
protected:
void resizeEvent(QResizeEvent *re) {
#ifndef SCALETOFIT
scene()->setSceneRect(QRect(QPoint(0,0), viewport()->size()));
if(!item) {
item = scene()->addRect(QRect(0,0,50,50), QPen(Qt::black), QBrush(Qt::red));
item->setPos(sceneRect().width()/2, 0);
}
#else
if(!item) {
item = scene()->addRect(QRect(0, 0, 1, 1), Qt::NoPen, QBrush(Qt::red));
item->setPos(3, 0);
}
fitInView(sceneRect(), Qt::KeepAspectRatio);
#endif
}
void keyPressEvent(QKeyEvent *ke) {
if(!item) return;
switch(ke->key()) {
case Qt::Key_Right: if(item->x() < sceneRect().width()-1) item->moveBy(1, 0); break;
case Qt::Key_Left: if(item->x() > 0) item->moveBy(-1, 0); break;
case Qt::Key_Up: if(item->y() > 0) item->moveBy(0, -1); break;
case Qt::Key_Down: if(item->y() < sceneRect().height()-1) item->moveBy(0, 1); break;
default: break;
}
}
private:
QGraphicsRectItem *item;
};

int main(int argc, char **argv) {
QApplication app(argc, argv);
GraphicsView view;
view.setScene(new QGraphicsScene);
#ifdef SCALETOFIT
view.scene()->setSceneRect(QRect(0, 0, 8, 16));
#endif
view.show();
return app.exec();
}