在图形界面框架中的事件都是先由视图进行接收,然后传递给场景,再由场景传递给图形项。通过键盘处理的话,需要设置焦点,在QGraphicsScene中使用setFoucesItem()函数可以设置焦点,或者图形项使用setFouce()获取焦点。
默认的如果场景中没有获取焦点,那么所有的键盘事件将会被丢弃。如果场景中的setFouce()函数或图形项获取了焦点,那么场景也会自动获取焦点。
对于鼠标悬停效果,QGraphicsScene会调度悬停事件。如果一个图形项可以接收悬停事件,那么当鼠标进入它的区域之中时,它就会收到一个GraphicsSceneHoverEnter事件。如果鼠标继续在图形项的区域之中进行移动,那么QGraphicsScene就会向该图形项发送GraphicsSceneHoverMove事件。当鼠标离开图形项的区域时,它将会收到一个GraphicsSceneHoverLeave事件。图形项默认是无法接收悬停事件的,可 以使用QGraphicsItem类的setAcceptHoverEvents()函数使图形项可以接收悬停事件。
所有的鼠标事件都会传递到当前鼠标抓取的图形项,一个图形项如果可以接收鼠标事件(默认可以)而且鼠标在它的上面被按下,那么它就会成为场景的鼠标抓取的图形项
事件主要分为:
- 鼠标事件
- 悬停事件
- 键盘事件
- 拖拽事件
- 上下文菜单事件
由于内容比较多,这里就单个单个介绍。
鼠标事件:
mouseDoubleClickEvent() | 鼠标双击事件 |
mouseMoveEvent() | 鼠标移动事件 |
mousePressEvent() | 鼠标点击事件 |
MouseReleaseEvent() | 鼠标松开事件 |
例子:
一个矩形项,鼠标单机的话为红色,双击的话为蓝色,移动的话为绿色,松开的话为黄色,
默认为黑色
MyItem.h文件
#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QMouseEvent>
class MyItem:public QGraphicsItem
{
public:
MyItem();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) ;//鼠标移动事件
void mousePressEvent(QGraphicsSceneMouseEvent *event) ;//鼠标点击事件
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) ;//鼠标松开事件
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) ;//鼠标双击事件
private:
QColor color;//颜色
};
#endif // MYITEM_H
MyItem.cpp文件
每次执行完之后要使用updata()更新一下数据,不然会卡顿。版本为(Qt5.9.9)
#include "myitem.h"
MyItem::MyItem()
{
color=QColor(Qt::black);//默认为黑色
}
QRectF MyItem::boundingRect() const
{
qreal penwidget=1;
return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
painter->setBrush(color);
painter->drawRect(0,0,100,100);//画矩形
}
void MyItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) //鼠标移动事件
{
color=QColor(Qt::green);
update();
}
void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event) //鼠标点击事件
{
setFocus();//设置焦点
color=QColor(Qt::red);
update();
}
void MyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) //鼠标松开事件
{
color=QColor(Qt::yellow);
update();
}
void MyItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) //鼠标双击事件
{
color=QColor(Qt::blue);
update();
}
main文件:
#include "widget.h"
#include "myitem.h"
#include <QApplication>
#include<QGraphicsScene>
#include<QGraphicsView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene(-200,-200,400,400); //场景
MyItem item; //项
scene.addItem(&item);
QGraphicsView view; //视图
view.setScene(&scene);
view.show();
return a.exec();
}
运行结果:
默认: 单击: 松开: 双击: 鼠标移动:
停靠事件:
hoverEnterEvent() | 悬停输入事件 |
hoverLeaveEvent() | 悬停离开事件 |
hoverMoveEvent() | 悬停移动事件 |
默认情况下,不会接收悬停事件,需要使用setAcceptHoverEvents()开启接收悬停事件。
例子:
默认为黑色,悬停离开为蓝色,悬停移动为绿色.
MyItem.h文件
#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QHoverEvent>
class MyItem:public QGraphicsItem
{
public:
MyItem();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) ;//悬停移动
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) ;//悬停进入
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) ;//悬停离开
private:
QColor color;//颜色
};
#endif // MYITEM_H
MyItem.cpp
#include "myitem.h"
MyItem::MyItem()
{
color=QColor(Qt::black);//默认为黑色
setAcceptHoverEvents(true);//开启接收悬停
}
QRectF MyItem::boundingRect() const
{
qreal penwidget=1;
return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
painter->setBrush(color);
painter->drawRect(0,0,100,100);//画矩形
}
void MyItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) //悬停移动
{
color=QColor(Qt::green);//绿色
update();
}
void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) //悬停输入
{
}
void MyItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) //悬停离开
{
color=QColor(Qt::blue);//蓝色
update();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene(-200,-200,400,400);
MyItem item;
scene.addItem(&item);
QGraphicsView view;
view.setScene(&scene);
view.show();
return a.exec();
}
键盘事件:
keyPressEvent | 键盘点击 |
keyReleaseEvent | 键盘松开 |
使用键盘事件需要注意的事项:
- 使用键盘事件的控件需要获取焦点,QGraphicsItem的话使用 setFocus()开启
- 需要使用setFlag()函数开启标志。(不开启这个不能使用,是一个坑)
enum QGraphicsItem::GraphicsItemFlag:(这几个是常见的,想要更加了解的话可以翻看官方文档)
QGraphicsItem::ItemIsMovable | 支持使用鼠标进行交互式移动。通过单击该项目然后拖动,该项目将与鼠标光标一起移动。 |
QGraphicsItem::ItemIsSelectable | 支持选择。启用此功能将启用 setSelected() 来切换项目的选择。 |
QGraphicsItem::ItemIsFocusable | 该项支持键盘输入焦点(即,它是输入项)。启用此标志将允许项目接受焦点 |
QGraphicsItem::ItemClipsToShape | 项目将剪辑到其自己的形状。该项目无法绘制或接收鼠标、平板电脑、拖放或将事件悬停在其形状之外。默认情况下处于禁用状态 |
QGraphicsItem::ItemClipsChildrenToShap | 项目将其所有后代的绘画剪辑成自己的形状。作为此项目的直接或间接子项的项不能在此项的形状之外绘制。 |
QGraphicsItem::ItemIgnoresTransformations | 项目忽略继承的变换,此标志可用于使文本标签项保持水平且不缩放,因此在转换视图时它们仍可读。 |
开启键盘的话,需要使用setFlag(QGraphicsItem::ItemIsFocusable)
例子:使用鼠标选取项,然后使用键盘的上下左右来移动矩形项,每次移动10
MyItem.h
#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QKeyEvent>
#include<QMouseEvent>
class MyItem:public QGraphicsItem
{
public:
MyItem();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
void keyPressEvent(QKeyEvent *event) ;//键盘点击
void mousePressEvent(QGraphicsSceneMouseEvent *event);//鼠标点击事件
private:
QColor color;//颜色
};
#endif // MYITEM_H
MyItem.cpp
#include "myitem.h"
MyItem::MyItem()
{
color=QColor(Qt::black);//默认为黑色
this->setFlag(QGraphicsItem::ItemIsFocusable);//设置标志
}
QRectF MyItem::boundingRect() const
{
qreal penwidget=1;
return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
painter->setBrush(color);
painter->drawRect(0,0,100,100);//画矩形
}
void MyItem::keyPressEvent(QKeyEvent *event) //键盘点击
{
if(event->key()==Qt::Key_Up)//向上
{
moveBy(0,-10);
}
else if(event->key()==Qt::Key_Down)//向下
{
moveBy(0,10);
}
else if(event->key()==Qt::Key_Left)//向左
{
moveBy(-10,0);
}
else if(event->key()==Qt::Key_Right)//向右
{
moveBy(10,0);
}
else{
}
}
void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
setFocus();//设置焦点
}
拖拽事件:
dragEnterEvent() | 拖动输入事件 |
dragLeaveEvent() | 拖拽离开事件 |
dragMoveEvent() | 拖动移动事件 |
dragEvent() | 拖拽事件 |
使用时需要注意的事项:
- 默认不会开启拖拽,需要使用 setAcceptDrops(true)开启
- 想要实现拖动控件的话还要开启 setFlag(QGraphicsItem::ItemIsMovable);
开启这两个函数即可实现拖拽控件:
//MyItem.h文件
#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QDropEvent>
class MyItem:public QGraphicsItem
{
public:
MyItem();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
private:
QColor color;//颜色
};
#endif // MYITEM_H
//MyItem.cpp文件
#include "myitem.h"
MyItem::MyItem()
{
color=QColor(Qt::black);//默认为黑色
this->setFlag(QGraphicsItem::ItemIsMovable);
setAcceptDrops(true);//开启拖拽
}
QRectF MyItem::boundingRect() const
{
qreal penwidget=1;
return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
painter->setBrush(color);
painter->drawRect(0,0,100,100);//画矩形
}
可以使用上面的几个事件实现你想要的结果,这里就不详细赘述。
上下文菜单事件:
通俗的讲就是: 你右键一个项,会弹出一些选择
contextMenuEvent() | 重新实现此事件处理程序以处理上下文菜单事件 |
void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QMenu menu;//创建一个菜单
QAction *removeAction = menu.addAction("Remove");//创建QAction创建行为
...//可以有多个
menu.exec(event->screenPos());//显示menu,设置在上下文菜单时鼠标光标在屏幕坐标中的位置
connect();//使用connect()来连接对应的处理结果
}
例子:
MyItem.h
#ifndef MYITEM_H
#define MYITEM_H
#include<QGraphicsItem>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QDropEvent>
#include<QDebug>
class MyItem:public QGraphicsItem
{
public:
MyItem();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget );
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;//上下文事件
private:
QColor color;//颜色
};
#endif // MYITEM_H
MyItem.cpp
#include "myitem.h"
#include <QGraphicsSceneContextMenuEvent>
#include <QMenu>
MyItem::MyItem()
{
color=QColor(Qt::black);//默认为黑色
this->setFlag(QGraphicsItem::ItemIsMovable);
setAcceptDrops(true);//开启拖拽
}
QRectF MyItem::boundingRect() const
{
qreal penwidget=1;
return QRectF(-penwidget/2,-penwidget/2,100+penwidget,100+penwidget);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
painter->setBrush(color);
painter->drawRect(0,0,100,100);//画矩形
}
void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QMenu menu;
QAction *A = menu.addAction("A");
QAction *B = menu.addAction("B");
QAction *C = menu.addAction("C");
QAction *D = menu.addAction("D");
QObject::connect(A,&QAction::triggered,[=]()
{
qDebug()<<"A";
});
QObject::connect(B,&QAction::triggered,[=]()
{
qDebug()<<"B";
});
QObject::connect(C,&QAction::triggered,[=]()
{
qDebug()<<"C";
});
QObject::connect(D,&QAction::triggered,[=]()
{
qDebug()<<"D";
});
menu.exec(event->screenPos());
}
main函数:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene(-200,-200,400,400);
MyItem item;
scene.addItem(&item);
QGraphicsView view;
view.setScene(&scene);
view.show();
return a.exec();
}
运行效果:
右键点击该控件:
分别点击ABCD,执行相应的输出:
参考文档:
QGraphicsItem Class | Qt Widgets 5.15.13