调用setPos()方法时,mousePressEvent()方法无法正常工作

时间:2013-06-15 14:48:00

标签: qt position mouseevent qgraphicsitem

我有一个类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()或我做错了什么?

欢迎任何帮助。

1 个答案:

答案 0 :(得分:1)

MenuItem()构造函数中,您使用mapToParent。但是您的商品没有任何父商品。因此,使用mapToParent毫无意义,在这种情况下,它等同于mapToScene。由于您的项目的初始位置是(0,0)并且未应用任何转换,mapToScene将返回其参数的值而不进行更改。所以它相当于setPos(200, 200)。在mapToParent中使用mapToScenesetPos的结果似乎很奇怪。我不明白你想做什么。

QGraphicsSceneMouseEvent::pos返回目标项坐标中事件的坐标。由于您在QGraphicsScene::keyPressEvent中使用它,因此事件尚未传播到任何项目,pos()始终返回(0,0)。文档不清楚,但我已经检查过了。

如果您没有使用setPos,则您的项目位置将为(0,0),而itemAt(0, 0)将找到您的项目(无论用户实际点击了什么点)。但是如果你确实使用setPositemAt(0, 0)会返回0,因为此时没有项目。如果您将event->pos()替换为event->scenePos(),它将正常工作。

然而,重新实现QGraphicsScene::keyPressEvent来点击项目是不寻常的。您应该重新实现QGraphicsItem::mousePressEvent。只有在单击项目时才会调用它,并且您不必检查事件的坐标来确定它。