我能在QGraphicsItem中获取鼠标事件吗?

18

我已经对 QGraphicsRectItem 进行了子类化,但它没有接收到任何鼠标事件。我看到其他类似的问题说我需要启用鼠标跟踪,但 setMouseTracking 在 QWidget 中,而 QGraphicsItem 似乎不是 QWidget。

我已经实现了 paint ,它可以工作。在我的子类化的 QGraphicsView 中我可以得到鼠标事件。

文档似乎认为我只需要重写 mousePressEvent 函数(例如),我就应该开始接收事件了。无论是否将 mousePressEvent 转发给我的 QGraphicsView 的超类,似乎都没有任何区别。

3个回答

24
在您的子类化QGraphicsView中,如果您希望鼠标事件传播到项,则需要调用覆盖的鼠标事件方法的默认实现。例如:
CustomView::mousePressEvent(QMouseEvent *event)
{
    // handle the event as you like

    QGraphicsView::mousePressEvent(event); // then call default implementation
}
如果您想接受悬停事件,需要调用QGraphicsItem::setAcceptHoverEvents(true);。否则,您无需启用任何特定的鼠标跟踪。
编辑:这里是一个完整的工作示例:
#include <QtGui>

class CustomView : public QGraphicsView
{
protected:
    void mousePressEvent(QMouseEvent *event)
    {
        qDebug() << "Custom view clicked.";
        QGraphicsView::mousePressEvent(event);
    }
};

class CustomItem : public QGraphicsRectItem
{
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        qDebug() << "Custom item clicked.";
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    CustomItem item;
    item.setRect(20, 20, 60, 60);

    QGraphicsScene scene(0, 0, 100, 100);
    scene.addItem(&item);

    CustomView view;
    view.setScene(&scene);
    view.show();
    return a.exec();
}

1
@Almo 你在子类化的QGraphicsScene中重写了任何鼠标事件吗? - Anthony
在我的QGraphicsView子类中,我创建了一个QGraphicsScene,并使用setScene调用它。我没有对QGraphicsScene进行子类化。 - Almo
1
@Almo请参见编辑中的工作示例。我猜你的QGraphicsItem :: boundingRect()返回的矩形不正确,或者如果你重新实现了QGraphicsItem::shape(),它也不正确。 - Anthony
2
啊,QGraphicsSceneMouseEvent。我一直在寻找QMouseEvent作为参数,因为QGraphicsView的重写使用它们。我没有注意到对于QGraphicsItem来说它们是不同的。你的例子指出了这一点。我感到很尴尬。 :) - Almo
@Anthony,我实现了一个QGView类,试图让它工作(尽管我并不真正需要它),但是我已经实现了一个QGScene类...我发现我只需要在继承的QGS类中添加mouse...Event(),所以我想补充一下(我认为)如果你将mouse...Event方法添加到视图和场景类中,它不会起作用,应该是其中之一。在我的情况下,视图捕获了它,并没有将其传递给继承的QGRectItem,但现在我解决了这个问题。谢谢大家! - user12927872
显示剩余2条评论

8

我曾经遇到过你所遇到的问题,并希望在Anthony非常好的回答上补充一些见解。这里是我编写的一个示例,展示了可以使用鼠标事件和键盘事件实现的一些功能。

请注意,事件不会传播到QGraphicsItemGroupQList<QGraphicsItem>中的QGraphicsItem(我花了一段时间才弄清楚这一点)。

#include <QtGui>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>

class CustomItem : public QGraphicsEllipseItem
{
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        if(event->button() == Qt::LeftButton) {
            if(event->modifiers() == Qt::ShiftModifier) {
                qDebug() << "Custom item left clicked with shift key.";
                // add the item to the selection
                setSelected(true);
            } else if(event->modifiers() == Qt::AltModifier){
                qDebug() << "Custom item left clicked with alt key.";
                // resize the item
                double radius = boundingRect().width() / 2.0;
                _center = QPointF(boundingRect().topLeft().x() + pos().x() + radius, boundingRect().topLeft().y() + pos().y() + radius);
                QPointF pos = event->scenePos();
                qDebug() << boundingRect() << radius << this->pos() << pos << event->pos();
                double dist = sqrt(pow(_center.x()-pos.x(), 2) + pow(_center.y()-pos.y(), 2));
                if(dist / radius > 0.8) {
                    qDebug() << dist << radius << dist / radius;
                    _isResizing = true;
                } else {
                    _isResizing = false;
                }
            } else {
                qDebug() << "Custom item left clicked.";
                QGraphicsItem::mousePressEvent(event);
                event->accept();
            }
        } else if(event->button() == Qt::RightButton) {
            qDebug() << "Custom item right clicked.";
            event->ignore();
        }
    }
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        if(event->modifiers() == Qt::AltModifier && _isResizing){
            QPointF pos = event->scenePos();
            double dist = sqrt(pow(_center.x()-pos.x(), 2) + pow(_center.y()-pos.y(), 2));
            setRect(_center.x()-this->pos().x()-dist, _center.y()-this->pos().y()-dist, dist*2, dist*2);
        } else if(event->modifiers() != Qt::AltModifier) {
            qDebug() << "Custom item moved.";
            QGraphicsItem::mouseMoveEvent(event);
            qDebug()<<"moved"<<pos();
        }
    }
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
    {
        if(event->modifiers() == Qt::AltModifier && _isResizing) {
            _isResizing = false;
        } else if(event->modifiers() != Qt::ShiftModifier) {
            QGraphicsItem::mouseReleaseEvent(event);
        }
    }

    int type() const
    {
        // Enable the use of qgraphicsitem_cast with this item.
        return UserType+1;
    }
private:
    QPointF _center;
    bool _isResizing;
};

class CustomScene : public QGraphicsScene
{
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        qDebug() << "Custom scene clicked.";
        QGraphicsScene::mousePressEvent(event);
        if(!event->isAccepted()) {
            if(event->button() == Qt::LeftButton) {
                // add a custom item to the scene
                QPointF pt = event->scenePos();
                CustomItem * item = new CustomItem();
                item->setRect(pt.x()-25, pt.y()-25, 50, 50);
                item->setFlags(QGraphicsItem::ItemIsSelectable|
                              QGraphicsItem::ItemIsMovable);
                addItem(item);
            } else if(event->button() == Qt::RightButton) {
                // check whether there is an item under the cursor
                QGraphicsItem * itemToRemove = NULL;
                foreach(auto item, items(event->scenePos())) {
                    if(item->type() == QGraphicsItem::UserType+1) {
                        itemToRemove = item;
                        break;
                    }
                }
                if(itemToRemove) {
                    // remove the item from the graphicsScene
                    removeItem(itemToRemove);
                }
            }
        }
    }
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        qDebug() << "Custom scene moved.";
        QGraphicsScene::mouseMoveEvent(event);
    }
    void keyPressEvent(QKeyEvent * event) {
        if(event->key() == Qt::Key_Backspace) {
            // remove all selected items
            qDebug() << "selected items" << selectedItems().size();
            while(!selectedItems().isEmpty()) {
                removeItem(selectedItems().front());
            }
        } else {
            QGraphicsScene::keyPressEvent(event);
        }
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    CustomItem item;
    item.setRect(20, 20, 60, 60);
    item.setFlags(QGraphicsItem::ItemIsSelectable|
                  QGraphicsItem::ItemIsMovable);

    CustomScene scene;
    scene.setSceneRect(0, 0, 500, 500);
    scene.addItem(&item);

    QGraphicsView view;
    view.setScene(&scene);
    view.show();
    return a.exec();
}

希望这也能有所帮助!


3

我曾经遇到过一个类似的问题,即视图不能接受鼠标点击。问题在于我需要启用该视图 ( ui->view->setEnabled(true) )。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接