Mouse interaction issues after adding items into the QGraphicsScene
-
- I've set the item to setAcceptedMouseButtons(0) but it still shows up in mousePress() function.
- In order to select a QGraphicsEllipseItem, I need to click on the tiny left top corner of the oval shape. I override shape() for QGraphicsEllipseItem and still can't get the area clickable to return in mousePress().
BTW, I'm new in Qt, and thank you for helping.
-
Please show some code, and we may be able to help.
-
- Here is how I setAccceptedMouseButton(0):
...
lRect = dScene->addRect(lLeftX, lTopY, lRightX-lLeftX, lFontHeight, lPen, QBrush(*lColor));
lRect->setFlag(QGraphicsItem::ItemIgnoresTransformations);
lRect->setAcceptedMouseButtons(0);
....
And in the class that inherited from QGraphicsView:
void myViewCls::mousePressEvent(QMouseEvent* xEvent)
{
qDebug() << "myViewCls::mousePressEvent, Pos? " << xEvent->pos();
QPointF lPoint = mapToScene(xEvent->pos());
qDebug() << "myViewCls::mousePressEvent, Scene Pos? " << lPoint;
QGraphicsItem* lItem = dScene->itemAt(lPoint, transform());
qDebug() << "Item Pressed? " << lItem;
if (lItem!= NULL)
qDebug() << "Found item type? " << lItem->type();QGraphicsView::mousePressEvent(xEvent);
}
And the qDebug() just keep showing the lRect info when I click on that region.
- This is the shape() I overwrite:
QPainterPath QGraphicsEllipseItem::shape() const
{
QPainterPath lPath;
QRectF lRect = rect();
QPolygon lPg;
lPg << QPoint(rect().top(), rect().left());
lPg << QPoint(rect().top(), rect().right());
lPg << QPoint(rect().bottom(), rect().right());
lPg << QPoint(rect().bottom(), rect().left());
lPath.addPolygon(lPg);
return lPath;
}
But the mousePressEvent only takes the very top and very left point to recognize the oval I drew. I thought by default the width and height should be included too, but even after I overwrite the shape, it doesn't work. Is it because of the itemAt restriction?
Thank you for any help anyone can provide! I"m stuck!
-Michelle
- Here is how I setAccceptedMouseButton(0):
-
- Here is how I setAccceptedMouseButton(0):
...
lRect = dScene->addRect(lLeftX, lTopY, lRightX-lLeftX, lFontHeight, lPen, QBrush(*lColor));
lRect->setFlag(QGraphicsItem::ItemIgnoresTransformations);
lRect->setAcceptedMouseButtons(0);
....
And in the class that inherited from QGraphicsView:
void myViewCls::mousePressEvent(QMouseEvent* xEvent)
{
qDebug() << "myViewCls::mousePressEvent, Pos? " << xEvent->pos();
QPointF lPoint = mapToScene(xEvent->pos());
qDebug() << "myViewCls::mousePressEvent, Scene Pos? " << lPoint;
QGraphicsItem* lItem = dScene->itemAt(lPoint, transform());
qDebug() << "Item Pressed? " << lItem;
if (lItem!= NULL)
qDebug() << "Found item type? " << lItem->type();QGraphicsView::mousePressEvent(xEvent);
}
And the qDebug() just keep showing the lRect info when I click on that region.
- This is the shape() I overwrite:
QPainterPath QGraphicsEllipseItem::shape() const
{
QPainterPath lPath;
QRectF lRect = rect();
QPolygon lPg;
lPg << QPoint(rect().top(), rect().left());
lPg << QPoint(rect().top(), rect().right());
lPg << QPoint(rect().bottom(), rect().right());
lPg << QPoint(rect().bottom(), rect().left());
lPath.addPolygon(lPg);
return lPath;
}
But the mousePressEvent only takes the very top and very left point to recognize the oval I drew. I thought by default the width and height should be included too, but even after I overwrite the shape, it doesn't work. Is it because of the itemAt restriction?
Thank you for any help anyone can provide! I"m stuck!
-Michelle
@MShao
Help me understand what you are doing exactly. So you have not created a QGraphicsEllipseItem of your own, with something likeclass MyEllipseItem : public QGraphicsEllipseItem { .... your stuff };
You are just overriding the QGraphicsEllipseItem functions directly?
- Here is how I setAccceptedMouseButton(0):
-
No, I don't have my own class, because I don't have my own stuff to do. All I'm doing is drawing the oval, and then I need to click it to get it's data in order to do something.
Or have the tooltip for it. I just tried the tooltip and it's not working either. I'm sure there is something I should be setting that I didn't.
A basic question, if I'm draing an Ellipse with the x, y and height and width, why is the boundingRect not having this area as default? Why do we need to always overwrite boundingRect?Thank you.
-
No, I don't have my own class, because I don't have my own stuff to do. All I'm doing is drawing the oval, and then I need to click it to get it's data in order to do something.
Or have the tooltip for it. I just tried the tooltip and it's not working either. I'm sure there is something I should be setting that I didn't.
A basic question, if I'm draing an Ellipse with the x, y and height and width, why is the boundingRect not having this area as default? Why do we need to always overwrite boundingRect?Thank you.
@MShao
Yes you do. I think you will make things easier for yourself if you subclass your graphics ellipse the way that is recommended in the docs. Especially if you need to overwrite the shape and paint functions. It is an easy thing to do and your item will begin to behave the way that all items are supposed to.
I am sure you have seen the docs about how to do it here.
There is code for a simple example of a subclassed QGraphicsItem i have posted previously here.
It is a different shape from yours but you might find it useful. -
Hi @kenchan
Thank you for your help. Question, why do we have our own "paint"? In the example of the doc:void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
painter->drawRoundedRect(-10, -10, 20, 20, 5, 5);
}Why do we call QPainter->drawRoundRect()? Shouldn't we just call QGraphicsScene->addEllipse() directly?
Now I'm confused about when to use QPainter->drawXXX() and when to use QGraphicsScene->addXXXX().
Thank you again for your explanation, Ken.
-
Hi @kenchan
Thank you for your help. Question, why do we have our own "paint"? In the example of the doc:void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
painter->drawRoundedRect(-10, -10, 20, 20, 5, 5);
}Why do we call QPainter->drawRoundRect()? Shouldn't we just call QGraphicsScene->addEllipse() directly?
Now I'm confused about when to use QPainter->drawXXX() and when to use QGraphicsScene->addXXXX().
Thank you again for your explanation, Ken.
@MShao
The example is just an example of the minimum subclass you can do with a QGraphicsItem. It shows that you can use the painter to draw anything you want. All graphics items call the QPainter to paint themselves. The example is drawing a shape that you can't draw with a standard QGraphicsItem, one which has round corners.
If you were to call QGraphicsScene->addXXX from inside your own graphics item you would have to keep track of it and manage it. It is far easier and natural to do all your own paint shape and bounding box management for your own class directly. You can create very intelligent objects that way if you need to.
If you don't need all that don't subclass a QGraphicsItem I suggest you just use the standard items and manipulate them using the standard functions.You probably would not actually subclass the QGraphicsEllipseItem anyway, just the QGraphicsItem class.
class MyEllipseItem : public QGraphicsItem { ... my stuff };
Just to be clear, if you just want to use the standard QGraphicsItems you don't need to implement paint or bounding box etc. for them. In fact you can't do that if you don't overwrite them like that because those functions belong the QGraphicsItem class.
-
@MShao
The example is just an example of the minimum subclass you can do with a QGraphicsItem. It shows that you can use the painter to draw anything you want. All graphics items call the QPainter to paint themselves. The example is drawing a shape that you can't draw with a standard QGraphicsItem, one which has round corners.
If you were to call QGraphicsScene->addXXX from inside your own graphics item you would have to keep track of it and manage it. It is far easier and natural to do all your own paint shape and bounding box management for your own class directly. You can create very intelligent objects that way if you need to.
If you don't need all that don't subclass a QGraphicsItem I suggest you just use the standard items and manipulate them using the standard functions.You probably would not actually subclass the QGraphicsEllipseItem anyway, just the QGraphicsItem class.
class MyEllipseItem : public QGraphicsItem { ... my stuff };
Just to be clear, if you just want to use the standard QGraphicsItems you don't need to implement paint or bounding box etc. for them. In fact you can't do that if you don't overwrite them like that because those functions belong the QGraphicsItem class.