GraphicsView支持事件传播体系结构,可以使图元在场景scene中得到提高了已被的精确交互能力。图形视图框架中的事件都是首先由视图进行接收,然后传递给场景,再由场景给相应的图形项。
对于键盘鼠标事件,scene会传递给获得焦点的图形项。如果场景没有获得焦点,那键盘事件会丢弃;如果调用场景setFocus()或者场景中的一个图形项获得了焦点,那么场景会自动获得焦点;如果场景丢失了焦点(如调用clearFocus())而其中一个图形项获得焦点那场景会保存这个图形项的焦点信息。
图形项默认无法接收悬停事件,可以使用QGraphicsItem的setAcceptHoverEvents()函数使图形项可以接收悬停事件。
(1)五个图形项的运行图如下图所示。
#ifndef MYSCENE_H #define MYSCENE_H #include <QGraphicsScene> #include <QGraphicsSceneMouseEvent> #include <QPaintEvent> #include <QKeyEvent> class MyScene : public QGraphicsScene { Q_OBJECT public: explicit MyScene(QObject *parent = 0); protected: void keyPressEvent(QKeyEvent *event); void mousePressEvent(QGraphicsSceneMouseEvent *event); signals: public slots: }; #endif // MYSCENE_H
#include "myscene.h" MyScene::MyScene(QObject *parent) : QGraphicsScene(parent) { clearFocus(); } void MyScene::keyPressEvent(QKeyEvent *event) { qDebug("*********MyScene::keyPressEvent***************"); return QGraphicsScene::keyPressEvent(event); } void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { qDebug("*********MyScene::mousePressEvent***************"); QGraphicsScene::mousePressEvent(event); }
#ifndef MYVIEW_H #define MYVIEW_H #include <QGraphicsView> class MyView : public QGraphicsView { Q_OBJECT public: explicit MyView(QWidget *parent = 0); protected: void keyPressEvent(QKeyEvent *event); void mousePressEvent(QMouseEvent *event); void paintEvent(QPaintEvent * event); void mouseMoveEvent(QMouseEvent *event); signals: public slots: }; #endif // MYVIEW_H
#include "myview.h" #include <QKeyEvent> MyView::MyView(QWidget *parent) : QGraphicsView(parent) { } void MyView::keyPressEvent(QKeyEvent *event) { qDebug("*********MyView::keyPressEvent***************"); switch (event->key()) { case Qt::Key_Left : scale(1.2, 1.2); break; case Qt::Key_Right : scale(1 / 1.2, 1 / 1.2); break; case Qt::Key_Up : rotate(30); break; } QGraphicsView::keyPressEvent(event); } void MyView::mousePressEvent(QMouseEvent *event) { qDebug("************MyView::mousePressEvent*****************"); QGraphicsView::mousePressEvent(event); } void MyView::paintEvent(QPaintEvent *event) { qDebug("************MyView::paintEvent*****************"); QGraphicsView::paintEvent(event); } void MyView::mouseMoveEvent(QMouseEvent *event) { //qDebug("************MyView::mouseMoveEvent*****************"); QGraphicsView::mouseMoveEvent(event); }
#ifndef MYITEM_H #define MYITEM_H #include <QGraphicsItem> #include <QGraphicsSceneEvent> class MyItem : public QGraphicsItem { public: MyItem(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setColor(const QColor &color) { brushColor = color; } protected: void keyPressEvent(QKeyEvent *event); void mousePressEvent(QGraphicsSceneMouseEvent *event); void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent (QGraphicsSceneHoverEvent * event); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); private: QColor brushColor; }; #endif // MYITEM_H
#include "myitem.h" #include <QPainter> #include <QCursor> #include <QKeyEvent> #include <QGraphicsSceneHoverEvent> #include <QGraphicsSceneContextMenuEvent> #include <QMenu> MyItem::MyItem() { brushColor = Qt::red; setFlag(QGraphicsItem::ItemIsFocusable); setFlag(QGraphicsItem::ItemIsMovable); //setAcceptHoverEvents(true); } QRectF MyItem::boundingRect() const { qreal adjust = 0.5; return QRectF(-10 - adjust, -10 - adjust, 20 + adjust, 20 + adjust); } void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { qDebug("************MyItem::paint*****************"); if(hasFocus()) { painter->setPen(QPen(QColor(255,255,255,200))); } else { painter->setPen(QPen(QColor(100,100,100,100))); } painter->setBrush(brushColor); painter->drawRect(-10, -10, 20, 20); } // 鼠标按下事件处理函数,设置被点击的图形项获得焦点,并改变光标外观 void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { qDebug("************MyItem::mousePressEvent*****************"); setFocus(); setCursor(Qt::ClosedHandCursor); } // 键盘按下事件处理函数,判断是否是向下方向键,如果是,则向下移动图形项 void MyItem::keyPressEvent(QKeyEvent *event) { qDebug("************MyItem::keyPressEvent*****************"); if(event->key() == Qt::Key_Down) moveBy(0, 10); } // 悬停事件处理函数,设置光标外观和提示 void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { qDebug("************MyItem::hoverEnterEvent*****************"); setCursor(Qt::OpenHandCursor); setToolTip("I am item"); } void MyItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { qDebug("************MyItem::hoverLeaveEvent*****************"); setCursor(Qt::ArrowCursor); } // 右键菜单事件处理函数,为图形项添加一个右键菜单 void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { QMenu menu; QAction *moveAction = menu.addAction("move back"); QAction *actAction = menu.addAction("test"); QAction *selectedAction = menu.exec(event->screenPos()); if(selectedAction == moveAction) { setPos(0, 0); } } void MyItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { qDebug("************MyItem::mouseMoveEvent*****************"); QGraphicsItem::mouseMoveEvent(event); }
#include <QApplication> #include "myitem.h" #include "myview.h" #include "myscene.h" #include <QTime> int main(int argc,char* argv[ ]) { QApplication app(argc,argv); qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); MyScene scene; scene.setSceneRect(-200, -150, 400, 300); for(int i = 0; i < 5; ++i) { MyItem *item = new MyItem; item->setColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256)); item->setPos(i * 50 - 90, -50); scene.addItem(item); } MyView view; view.setScene(&scene); view.setBackgroundBrush(QPixmap(":/background.png")); view.show(); return app.exec(); }
分析:mousePressEven鼠标按下事件由View—Scene—Item
分析:事件项Item没有获得焦点时,mousePressEven鼠标按下事件只由View传递到Scene。
分析:事件项Item的悬停事件,在构造函数中设置了setAcceptHoverEvents(true)。
(1)本文只是GraphicsView框架事件处理的部分测试数据解析,若对其他的事件感兴趣可以下载本代码进行自己的测试开发工作。
(2)源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/7786371)。
(3)本人思路有限,若有更好的设计建议,也可发邮件沟通,在此先感谢!邮箱地址yang.ao@i-soft.com.cn。