PDA

View Full Version : Coordinates of a widget inside QGridLayout



kolqhoz
29th March 2014, 11:05
Hi everyone !

I am trying to find the coordinates of a class derived from a QWidget inside a QGridLayout relative to its parent. I have tried several things such as x() and y() and pos() (returned 0,0) from QWidget class, adding a QRect to the class and using getCoords from QRect class and the mapToParent class from QWidget but it always returns 0. I can't seem to find the anser so I seek your help !

thanks in advance for your help, you can find the code of my program attached to this post.

render_area.cpp


#include "render_area.hpp"

#include <GL/glu.h>
#include <iostream>
#include <cmath>

#include <QPainter>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QGridLayout>


render_area::render_area(QWidget *parent)
:QWidget(parent)
{
setFocusPolicy(Qt::StrongFocus);
setBackgroundRole(QPalette::Base);
setAutoFillBackground(true);

bar=new QRect(width()/2,height()+50,150,10);
grid=new Grid(this);
grid->fill_grid(this);
std::cout<<"Grid filled !"<<std::endl;

QPoint point;
point=grid->getBrick(5)->pos();
grid->getBrick(5)->mapToParent(point);
std::cout<<point.y()<<std::endl;

dt=1/30.0f;
connect(&timer, SIGNAL(timeout()), this, SLOT(update_timer()));
timer.start(5);

draw_circle=true;

x_old=0;
y_old=0;
x_old2=0;
y_old2=0;

xc=500;
yc=500;
diametre=15;

vxc=20.0f;
vyc=-20.0f;

is_fixed=false;
}

render_area::~render_area()
{}



void render_area::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.drawRect(*bar);

QPen pen;
pen.setWidth(1.0);
pen.setColor(Qt::blue);
painter.setPen(pen);

QBrush brush = painter.brush();
brush.setColor(Qt::gray);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);

if(draw_circle)
painter.drawEllipse(xc,yc,diametre,diametre);
}

void render_area::change_draw_circle()
{
draw_circle=!draw_circle;
repaint();
}

void render_area::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
case Qt::Key_Right:
bar->translate(15,0);
break;
case Qt::Key_Left:
bar->translate(-15,0);
break;
default:
break;
}
}

void render_area::mousePressEvent(QMouseEvent *event)
{
x_old=event->x();
y_old=event->y();
std::cout<<event->x()<<"|"<<event->y()<<std::endl;
is_fixed=true;
}

void render_area::mouseReleaseEvent(QMouseEvent *event)
{

float x=event->x();
float y=event->y();


vxc=60*(x-x_old2);
vyc=60*(y-y_old2);

is_fixed=false;

}

void render_area::mouseMoveEvent(QMouseEvent *event)
{
int x=event->x();
int y=event->y();

float R=diametre/2.0f;
float x0=xc+R;
float y0=yc+R;

if( (x-x0)*(x-x0)+(y-y0)*(y-y0)<R*R )
{
xc+=(x-x_old);
yc+=(y-y_old);
}

x_old2=x_old;
y_old2=y_old;
x_old=x;
y_old=y;

repaint();
}

void render_area::update_timer()
{
int x1,x2,y1,y2;
bar->getCoords(&x1,&y1,&x2,&y2);

if(is_fixed==false)
{
//gestion du sol
if(yc+diametre>height())
{
vyc=-vyc;

}

if(xc>x1 && xc<x1+150)
{
if(yc+diametre>y1)
{
vyc=-vyc;
}
}
//plafond
if(yc-diametre<0)
{
vyc=-vyc;
}

//bord droit
if(xc+diametre>width())
{
vxc=-vxc;
}

//bord gauche
if(xc<0)
{
vxc=-vxc;
}

//integration (Euler explicite)
xc=xc+dt*vxc;
yc=yc+dt*vyc;

}
repaint();
}

Grid* render_area::getGrid() const
{
return grid;
}


grid.cpp


#include "grid.hpp"

Grid::Grid(QWidget *parent) :
QWidget(parent)
{
grid=new QGridLayout(parent);
grid->setContentsMargins(0,0,0,0);
grid->setAlignment(Qt::AlignTop);
grid->setSpacing(2);
}

void Grid::fill_grid(QWidget* parent)
{
for (int i=0;i<10;i++)
{
for (int j=0;j<12;j++)
{
brick* fillingBrick=new brick(parent);
grid->addWidget(fillingBrick->getLabel(),j,i);
qDebug()<<fillingBrick->parentWidget();
brickVector.push_back(fillingBrick);
}
}
}

std::vector<brick*> Grid::getBrickVector() const
{
return brickVector;
}

brick* Grid::getBrick(int indice)
{
return brickVector.at(indice);
}

QGridLayout* Grid::getGrid() const
{
return grid;
}

brick.cpp


#include "brick.hpp"

brick::brick(QWidget *parent) :
QWidget(parent)
{
label=new QLabel;
brickPic=new QPixmap(100,15);
brickPic->fill(QColor(255,0,0));
label->setPixmap(*brickPic);
}

brick::~brick()
{
}

QLabel* brick::getLabel() const
{
return label;
}

QPixmap* brick::getPixmap() const
{
return brickPic;
}

QRect* brick::getRect() const
{
return rect;
}

void brick::setRect(QRect recttmp)
{
int x,y,w,h;
recttmp.getRect(&x,&y,&w,&h);
rect=new QRect(x,y,w,h);
}

I'll put here the things I tried to solve the problem :
in the fill_grid member function : tried to change the parent of the brick by using setparent(parent) -> failed
in the render_area contructor : tried adding show() before getting grid->getBrick(5)->pos() failed
Even after showing the main windows fenetre.getRender()->getGrid()->getBrick(5)->x() shows 0
in fill_grid member function : qDebug() << fillingBrick->parentWidget() shows "render_area(0x64f570)" which is good but the brick still can't find its position inside its parent (0,0)

ChrisW67
30th March 2014, 06:31
It is hard to say with your roundabout code exactly where the problem is. You place objects of type brick in your grid layout but your brick widget has no layout, and the label parented to it is not related to the size of that brick. I see no purpose in Grid being a QWidget. You seem to ignore the content in render_widget in your paintEvent() anyway.

The parent widget has no size, the layout has not been invoked, and the child widgets have not been sized when you query the size in the constructor. The geometry of widgets in a layout is available after the layout has been shown:


#include <QtGui>

class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *p =0): QWidget(p) {
layout = new QGridLayout(this);
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
QLabel *label = new QLabel(QString("%1:%2").arg(i).arg(j));
layout->addWidget(label, i, j);
}
}

resize(640, 480);

QTimer::singleShot(0, this, SLOT(doit()));
}
public slots:
void doit() {
qDebug() << "Cell rect:" << layout->cellRect(1, 1);
QWidget *widget = layout->itemAtPosition(1, 1)->widget();
qDebug() << "Widget:" << widget->pos() << widget->geometry();
// Cell rect: QRect(218,165 204x150)
// Widget: QPoint(218,165) QRect(218,165 204x150)
}
private:
QGridLayout *layout;
};

int main(int argc, char **argv) {
QApplication app(argc, argv);
Widget w;
w.show();
return app.exec();
}
#include "main.moc"