【问题标题】:mousePressEvent() method is not working as expected when calling setPos() method调用 setPos() 方法时,mousePressEvent() 方法未按预期工作
【发布时间】:2013-06-15 23:16:21
【问题描述】:

我有一个继承自 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() 还是我做错了什么?

欢迎任何帮助。

【问题讨论】:

    标签: qt position mouseevent qgraphicsitem


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 感谢您的回答@Riateche!你是对的,'mapToParent()' 方法没有意义,这只是一个尝试。
    • 重新实现QGraphicsItem::mousePressEvent时,如何识别哪个MenuItem,例如Menu类里面的“New Game”被点击了?您会在QGraphicsItem::mousePressEvent 中发出信号还是有更好的解决方案?
    • 我认为发出一些自定义的clicked() 信号是可以的。但请注意,如果要使用信号,则需要从 QGraphicsItemQObject 派生。您也可以添加Menu::itemClicked(MenuItem*) 方法并从MenuItem::mousePressEvent 调用它。
    猜你喜欢
    • 1970-01-01
    • 2019-04-22
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 2020-10-04
    • 2018-12-22
    相关资源
    最近更新 更多