我有一个类MenuItem,它继承自QGraphicsItem并重新实现boundingRect(),shape(),paint(),outlineRect():
MenuItem::MenuItem(const QString& qsText, qreal qrYPos)
{
m_qsText = qsText;
m_BackgroundColor = Qt::white;
m_OutlineColor = Qt::darkBlue;
m_TextColor = Qt::darkGreen;
qDebug() << pos();
setPos(mapToParent(200,200)); //<-- when calling this method, mousePressEvent()
// behaves not as expected
qDebug() << pos();
}
QRectF MenuItem::boundingRect() const
{
const int iMargin = 1;
return outlineRect().adjusted(-iMargin, -iMargin, +iMargin, +iMargin);
}
QPainterPath MenuItem::shape() const
{
QRectF rect = outlineRect();
QPainterPath path;
path.addRect(rect);
return path;
}
void MenuItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPen pen(m_OutlineColor);
painter->setPen(pen);
painter->setBrush(m_BackgroundColor);
QRectF rect = outlineRect();
painter->drawRect(rect);
painter->setPen(m_TextColor);
painter->drawText(rect, Qt::AlignCenter, m_qsText);
}
void MenuItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "Item Mouse Pressed";
}
QString MenuItem::getText() const
{
return m_qsText;
}
QRectF MenuItem::outlineRect() const
{
const int iPadding = 8;
QFontMetricsF metrics = QFontMetricsF(QApplication::font());
QRectF rect = metrics.boundingRect(m_qsText);
rect.adjust(-iPadding, -iPadding, +iPadding, +iPadding);
rect.translate(-rect.center());
return rect;
}
在另一个名为Menu的类中,它继承自QGraphicsScene,我添加了一个MenuItem实例:
Menu::Menu()
: QGraphicsScene()
{
setSceneRect(0, 0, 800, 600);
m_miNewGame = new MenuItem("New Game", 300);
this->addItem(m_miNewGame);
//m_miNewGame->setPos(200,200);
}
Menu类重新实现mousePressEvent
void Menu::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
//qDebug() << "Menu Mouse Pressed";
MenuItem *gi = dynamic_cast<MenuItem*>(itemAt(event->pos(), QTransform()));
if (gi)
qDebug() << gi->getText();
QGraphicsScene::mousePressEvent(event); // this forwards the event to the item
if (itemAt(event->pos(), QTransform()))
{
qDebug() << "You Pressed an Item";
}
}
如果我在MenuItem构造函数中使用setPos()方法,MenuItem位于右边但在Menu :: mousePressEvent()方法内,则从itemAt()返回的MenuItem *始终为NULL。
省略setPos()方法,MenuItem停留在场景的左上角(0,0),并按预期处理mousePressEvents:使用getText()方法返回MenuItems文本。
调用setPos()时,为什么MenuItem *为NULL? 我是否必须重新实现setPos()或我做错了什么?
欢迎任何帮助。
答案 0 :(得分:1)
在MenuItem()
构造函数中,您使用mapToParent
。但是您的商品没有任何父商品。因此,使用mapToParent
毫无意义,在这种情况下,它等同于mapToScene
。由于您的项目的初始位置是(0,0)并且未应用任何转换,mapToScene
将返回其参数的值而不进行更改。所以它相当于setPos(200, 200)
。在mapToParent
中使用mapToScene
或setPos
的结果似乎很奇怪。我不明白你想做什么。
QGraphicsSceneMouseEvent::pos
返回目标项坐标中事件的坐标。由于您在QGraphicsScene::keyPressEvent
中使用它,因此事件尚未传播到任何项目,pos()
始终返回(0,0)。文档不清楚,但我已经检查过了。
如果您没有使用setPos
,则您的项目位置将为(0,0),而itemAt(0, 0)
将找到您的项目(无论用户实际点击了什么点)。但是如果你确实使用setPos
,itemAt(0, 0)
会返回0,因为此时没有项目。如果您将event->pos()
替换为event->scenePos()
,它将正常工作。
然而,重新实现QGraphicsScene::keyPressEvent
来点击项目是不寻常的。您应该重新实现QGraphicsItem::mousePressEvent
。只有在单击项目时才会调用它,并且您不必检查事件的坐标来确定它。