QGraphicsPixmapItem 在 QGraphicsScene 中处理鼠标事件的问题

问题描述 投票:0回答:1

我创建了一个对象:

class Button : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
public:
    Button();
    virtual QRectF boundingRect() const override;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;

    // QGraphicsItem interface
protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
signals:
    void clicked();
private:
    bool m_pressed;
    QPixmap m_buttonPixmap, m_pressedButtonPixmap;
};

接下来我实现了几个功能:

Button::Button()
    : m_pressed(false)
{
    m_buttonPixmap = PixmapManager::Instance()->getPixmap(PixmapManager::Button);
    m_pressedButtonPixmap = PixmapManager::Instance()->getPixmap(PixmapManager::PressedButton);
    setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
}

QRectF Button::boundingRect() const
{
    return QRectF(-m_buttonPixmap.width() / 2.0f,
                  -m_buttonPixmap.height() / 2.0f,
                  m_buttonPixmap.width(),
                  m_buttonPixmap.height());

}

void Button::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    if (m_pressed) {
        //painter->drawPixmap(0,0, m_pressedButtonPixmap);

    }
    else {
        painter->setBrush(Qt::red);
        painter->drawRect(boundingRect());
        //painter->drawPixmap(0,0, m_buttonPixmap);
    }
}

void Button::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "pressed ";
    m_pressed = true;
    update();
    QGraphicsPixmapItem::mousePressEvent(event);
}

void Button::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "released ";
    m_pressed = false;
    update();
    QGraphicsPixmapItem::mouseReleaseEvent(event);
}

我还创建了一个带有 Button 项目的 QGraphicsScene:

MenuScene::MenuScene(QObject *parent)
    : QGraphicsScene(parent)
{
    setSceneRect(0,0, SCREEN::PHYSICAL_SIZE.width(), SCREEN::PHYSICAL_SIZE.height());
    addItem(&m_startButton);
}

void MenuScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "Scene pressed";
    QGraphicsScene::mousePressEvent(event);
}

void MenuScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "Scene released";
    QGraphicsScene::mouseReleaseEvent(event);
}

如果我点击一个按钮,我只能从 MenuScene 获得信息,例如“按下场景”/“释放场景”

在main.cpp中我使用:

    MenuScene* ms = new MenuScene();
    QGraphicsView gv;
    gc.show();

我尝试使用: m_startButton.setAcceptedMouseButtons(Qt::AllButtons); m_startButton.setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable); 但没有结果。

c++ qt qgraphicsscene qgraphicspixmapitem
1个回答
0
投票

鼠标碰撞检测始终使用视图的

items()
函数和
Qt::IntersectsItemShape
标志来检查哪些项目可能受到鼠标事件的影响,这意味着结果始终基于项目的
shape()

虽然 QGraphicsItem 的默认行为是基于

boundingRect()
返回 QPainterPath,但并非所有子类都是这种情况,包括 QGraphicsPixmapItem,它基于其像素图(并可能考虑其掩码)构造路径。

由于您从未在项目上调用

setPixmap()
,因此从
shape()
生成的路径为空,因此对于鼠标事件(以及其他项目的碰撞检测,无论其价值如何),它始终是透明

最简单的解决方案是在构造函数中调用

setPixmap(m_buttonPixmap)
,然后在相关鼠标事件处理程序中使用任一像素图再次调用
setPixmap()

或者,您可以覆盖

shape()
,创建一个 QPainterPath,使用
addRect(boundingRect())
,然后返回它(您还应该考虑缓存边界矩形和路径,以避免不必要的开销)。

但请注意,您实际上没有利用任何 QGraphicsPixmapItem 功能:您不仅没有使用它的偏移、转换模式或遮罩功能,而且最终还需要自己绘制像素图。
考虑到这一点,从一开始就对其进行子类化确实没有什么意义,您可能只需从 QGraphicsObject 继承,它已经从 QObject 和 QGraphicsItem 继承了。

© www.soinside.com 2019 - 2024. All rights reserved.