0

我有一个继承自 QGraphicsItem 并重新实现 boundingRect()、shape()、paint()、outlineRect() 的类 MenuItem:

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;
}

在另一个继承自 QGraphicsScene 的名为 Menu 的类中,我添加了一个 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() 还是我做错了什么?

欢迎任何帮助。

4

1 回答 1

1

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

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

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

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

于 2013-06-15T15:16:21.397 回答