PDA

View Full Version : Embeded QGraphicsProxyWidget away from boundingRect



qlands
13th June 2010, 15:55
Hi,

Hi, I'm embedding and widget into a scene with a QGraphicsProxyWidget but the embedded widget is away from its boundingRect. See following image

http://www.qlands.com/other_files/scene03.jpg

Here is the code that adds it:


QGraphicsProxyWidget *item = new QGraphicsProxyWidget;

comboWidget = new myComboBox;
item->setWidget(comboWidget);
comboWidget->setValue("Item 1");

QPointF draggedPoint;
draggedPoint.setX(100);
draggedPoint.setY(100);
myscene.addItem(item);
item->setPos(draggedPoint);
item->setFlag(QGraphicsItem::ItemIsMovable, true);
item->setFlag(QGraphicsItem::ItemIsSelectable, true);


I have been trying to move the widget to center the boundingRect but nothing seems to work.

Any ideas will be apppreciated,
Carlos.

wysota
13th June 2010, 17:26
What do you mean that the widget is "away from its boundingRect()"? Bounding rect of an item has nothing to do with its position on the scene.

qlands
13th June 2010, 17:49
Hi,

For example in the image that I posted I use the boundingRect of the item to draw the black small boxes. For this I capture the position of the boundingRect of the item in the scene and then I draw the small boxes around it. For other item types like polygons the small boxes are around the item because the polygon is centered on his boundingRect but not for Proxy widgets. See below for a polygon

http://www.qlands.com/other_files/scene04.jpg

Many thanks

wysota
13th June 2010, 21:10
Show the code please.

qlands
14th June 2010, 08:07
Here is the code that set the boxes around an item



void tnkdesignscene::showSelectionItems(QGraphicsItem *Item)
{
float xpos;
float ypos;

//The separation between the boundingRect of item and the boxes
separation = 10;

//tnkresizeitem is a class of QGraphicsPolygonItem. These are the boxes appearing around item
tnkresizeitem *titem;

//Get the position of the item;
xpos = Item->scenePos().x();
ypos = Item->scenePos().y();

//Upper left box
titem = new tnkresizeitem();
titem->setX(xpos - (Item->boundingRect().width()/2) -separation);
titem->setY(ypos - (Item->boundingRect().height()/2) - separation);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::UpperLeft);
addItem(titem);

//Lower right box
titem = new tnkresizeitem();
titem->setX(xpos + (Item->boundingRect().width()/2) + separation);
titem->setY(ypos + (Item->boundingRect().height()/2) + separation);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::LowerRight);
addItem(titem);


//Lower left box
titem = new tnkresizeitem();
titem->setX(xpos - (Item->boundingRect().width()/2) - separation);
titem->setY(ypos + (Item->boundingRect().height()/2) + separation);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::LowerLeft);
addItem(titem);


//Upper right box
titem = new tnkresizeitem();
titem->setX(xpos + (Item->boundingRect().width()/2) + separation);
titem->setY(ypos - (Item->boundingRect().height()/2) - separation);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::UpperRight);
addItem(titem);


//Top box
titem = new tnkresizeitem();
titem->setX(xpos);
titem->setY(ypos - (Item->boundingRect().height()/2) - separation);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::Top);
addItem(titem);


//Bottom box
titem = new tnkresizeitem();
titem->setX(xpos);
titem->setY(ypos + (Item->boundingRect().height()/2) + separation);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::Bottom);
addItem(titem);


//Left box
titem = new tnkresizeitem();
titem->setX(xpos - (Item->boundingRect().width()/2) - separation);
titem->setY(ypos);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::Left);
addItem(titem);


//Right box
titem = new tnkresizeitem();
titem->setX(xpos + (Item->boundingRect().width()/2) + separation);
titem->setY(ypos);
titem->setZValue(selItemZ);
titem->setResizePosition(tnkresizeitem::Right);
addItem(titem);

}


Here is the definition of tnkresizeitem used in the function


class tnkresizeitem : public QGraphicsPolygonItem
{
public:
enum { Type = UserType + 37 };
enum resizePositions { None, UpperLeft, LowerRight, UpperRight, LowerLeft, Top, Bottom, Left, Right };
tnkresizeitem();
int type() const { return Type; }
void setResizePosition(resizePositions position) {resizeposition = position;};
resizePositions getResizePosition() {return resizeposition;};
protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event); //Will change the color to blue
void hoverLeaveEvent(QGraphicsSceneHoverEvent * event); //Will change the color to black
resizePositions resizeposition; //Where the item is
};

wysota
14th June 2010, 09:57
You are assuming that the point of origin of the item's coordinate system is in the middle of the item which is not the case for proxy widget items where the origin is in top left corner of the item. Better use:


QPointF topLeft = item->mapToScene(item->boundingRect().topLeft());
QPointF bottomLeft = item->mapToScene(item->boundingRect().bottomLeft());
QPointF topRight = item->mapToScene(item->boundingRect().topRight());
QPointF bottomRight = item->mapToScene(item->boundingRect().bottomRight());

qlands
14th June 2010, 10:00
Here is an small application that re-creates the problem.



#include <QtCore>
#include <QtGui>

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QGraphicsScene scene;
scene.setSceneRect(0, 0, 800, 480);

QGraphicsProxyWidget *w = new QGraphicsProxyWidget;
w->setWidget(new QPushButton("Test"));
w->widget()->setGeometry(0,0,100,100); //Makes the pushbutton 100x100

//Creates a polygon of 100x100
QPolygonF poly;
poly << QPointF(-50, -50) << QPointF(50, -50)
<< QPointF(50, 50) << QPointF(-50, 50)
<< QPointF(-50, -50);

QGraphicsPolygonItem *p = new QGraphicsPolygonItem;

p->setPolygon(poly);

//Sets both polygon and proxy widget in the same position.
p->setPos(100,100);
w->setPos(100,100);
//This would look as if the proxy widget has a black border all around it but this does not work.


scene.addItem(w);
scene.addItem(p);
QGraphicsView view(&scene);
view.show();

return app.exec();
}


Thanks,
Carlos.

qlands
14th June 2010, 10:05
Thanks for the reply.

Is there any way to change the origin or move the internal widget?

wysota
14th June 2010, 10:16
You can always subclass the proxy and reimplement boundingRect() for it or place it in another item with a boundingRect fitting your design.

qlands
14th June 2010, 11:54
Hi,

I opted for sub-classing the proxy and reimplementing boudingrect but I still cant make it.

Here is the implementation:


QRectF boundingRect() const
{
QRectF newbound;
newbound.setWidth(widget()->geometry().width());
newbound.setHeight(widget()->geometry().height());
QPointF center;
center.setX(0);
center.setY(0);
newbound.moveCenter(center); //Centers the boundrect in 0,0 just like other types of items
return newbound;
};


Here is the result:
http://www.qlands.com/other_files/scene05.jpg

With this code is almost the same but just a quarter of the item is shown.

wysota
14th June 2010, 12:00
I don't think that's enough as paint() still paints starting with (0,0). You probably have to reimplement it as well and translate the painter before calling the base class implementation. An alternative would be to implement an "effect" for the item that would translate it to coordinates you expect. Then you wouldn't have to touch the proxy class itself assuring that you don't break the way events are handled, etc.

qlands
14th June 2010, 12:19
ok. I reimplemented the proxy paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)

How can I tell the painter to start somewhere and not 0,0?

qlands
14th June 2010, 12:59
I used the translate(x,y) but this mess up with the translations between the widget and proxy in the scene.

This may be a bit messy... I will follow your other suggestion of place it in another item with a boundingRect fitting your design.

Let me see if I can work out this suggestion.

qlands
14th June 2010, 16:35
I managed to do it by embedding the proxy into a QGraphicsRectItem.

Thanks a lot for your advice.

[CLOSED]

Carlos.