网站首页 > 技术文章 正文
一、简介
图形视图框架中的事件都是首先由视图进行接收,然后传递给场景,再由场景传递给相应的图形项。而对于键盘事件,它会传递给获得焦点的图形项,可以使用QGraphicsScene类的setFocusItem()函数或者图形项自身调用setFocus()函数来设置焦点图形项。默认的,如果场景没有获得焦点,那么所有的键盘事件都会被丢弃。场景中的图形项获得了焦点,场景也会自动获得焦点。
对于鼠标悬停效果,QGraphicsScene会调度悬停事件。如果一个图形项可以接收悬停事件,那么当鼠标进入它的区域之中时,它就会收到一个GraphicsSceneHoverEnter事件。如果鼠标继续在图形项的区域之中进行移动,那么QGraphicsScene就会向该图形项发送GraphicsSceneHoverMove事件。当鼠标离开图形项的区域时,它将会收到一个GraphicsSceneHoverLeave事件。图形项默认是无法接收悬停事件的,可 以使用QGraphicsItem类的setAcceptHoverEvents()函数使图形项可以接收悬停事件。
所有的鼠标事件都会传递到当前鼠标抓取的图形项,一个图形项如果可以接收鼠标事件(默认可以)而且鼠标在它的上面被按下,那么它就会成为场景的鼠标抓取的图形项。
二、实例
下面来看一个例子。新建空的Qt项目,名称为myView。完成后先向本项目中添加一个Myltem自定 义图形项,然后在myitem.h文件中声明boundingRect()和paint()两个纯虚函数,再声明并定义一个公共的用于设置图形项填充色的函数和变量,最后添加一些事件处理函数的声明,完成后myitem.h文件内容如下:
#ifndef MYITEM_H
#define MYITEM_H
#include <QGraphicsItem>
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 mousePressEvent(QGraphicsSceneMouseEvent *event);
//键盘按下事件处理函数,判断是否是向下方向键,如果是,则向下移动图形项
void keyPressEvent(QKeyEvent *event);
//悬停事件处理函数,设置光标外观和提示
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
//右键菜单事件处理函数,为图形项添加一个右键菜单
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
private:
QColor brushColor; //画刷颜色
};
#endif // MYITEM_H
使用了变量作为画刷的颜色,就可以动态指定图形项的填充色了,默认情况下图形项的填充色设置为红色。
然后myitem.cpp文件修改如下:
#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)
{
Q_UNUSED(option); //标明该参数没有使用
Q_UNUSED(widget);
//根据图形项是否获得焦点来使用不同颜色绘制图形项的轮廓
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)
{
Q_UNUSED(event);
setFocus();
setCursor(Qt::ClosedHandCursor);
}
//键盘按下事件处理函数,判断是否是向下方向键,如果是,则向下移动图形项
void MyItem::keyPressEvent(QKeyEvent *event)
{
//实现视图的下移
if(event->key() == Qt::Key_Down)
moveBy(0, 10);
}
//悬停事件处理函数,设置光标外观和提示
void MyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
setCursor(Qt::OpenHandCursor);
setToolTip("I am item");
}
//右键菜单事件处理函数,为图形项添加一个右键菜单
void MyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QMenu menu;
QAction *moveAction = menu.addAction("move back");
QAction *selectedAction = menu.exec(event->screenPos());
if(selectedAction == moveAction)
{
setPos(0, 0);
}
}
- 在鼠标按下事件处理函数中,为鼠标单击的图形项设置了焦点,这样当按下键盘时该图形项就会接收到按键事件。
- 然后是键盘按下事件处理函数,如果按下了键盘的向下方向键,那么获得焦点的图形项就会向下移动,这里使用了 moVeBy(qreal dx, qreal dy)函数,它用来进行相对移动,就是相对于当前位置在水平方向移动dx,在垂直方向移动dy。在进行项目移动时,经常使用到该函数。
- 然后是悬停事件处理函数,如果将鼠标光标移动到一个图形项上,可以看到光标外观改变了,而且出现了工具提示。
- 然后是右键菜单事件,在一个图形项上右击,就会弹出一个菜单,如果选中该菜单,那么图形项会移动到场景原点。
然后myview.h文件修改如下:
#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);
signals:
public slots:
};
#endif // MYVIEW_H
然后myview.cpp文件修改如下:
#include "myview.h"
#include <QKeyEvent>
MyView::MyView(QWidget *parent) :
QGraphicsView(parent)
{
}
//键盘按下事件处理函数
void MyView::keyPressEvent(QKeyEvent *event)
{
switch (event->key())
{
//数字“-”键
case Qt::Key_Plus :
scale(1.2, 1.2);
break;
//数字“+”键
case Qt::Key_Minus :
scale(1 / 1.2, 1 / 1.2);
break;
//右方向键
case Qt::Key_Right :
rotate(30);
break;
}
QGraphicsView::keyPressEvent(event);
}
这里使用不同的按键来实现视图的缩放和旋转等操作。一定要注意,在视图的事件处理函数的最后一定要调用QGraphicsView类的keyPressEvent()函数,不然在场景或者图形项中就无法再接收到该事件了。
最后修改main.cpp文件,并且将其内容更改如下:
#include <QApplication>
#include "myitem.h"
#include "myview.h"
#include <QTime>
int main(int argc,char* argv[ ])
{
QApplication app(argc,argv);
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
QGraphicsScene 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("../myView/background.png"));
view.show();
return app.exec();
}
这里在场景中添加了 5个图形项,分别为它们设置了随机颜色,然后将它们排成一行。可以使用键盘上的“ + ”和“-”键来放大和缩小视图,也可以使用向右方向键来旋转视图。
三、效果
执行程序,最初的效果如下:
按右方向键后,旋转视图后:
鼠标拖动图形项后:
文章转自博客园(fengMisaka):https://www.cnblogs.com/linuxAndMcu/p/11064518.html
猜你喜欢
- 2024-12-24 Excel VBA 用户窗体设置/一步一步代你设计EXCEL用户+密码登录界面
- 2024-12-24 家庭收支理财管理系统 Access数据库系统课程设计制作实例
- 2024-12-24 MFC界面库BCGControlBar v32.1 - 可视化管理器和主题升级
- 2024-12-24 DJYGUI系列文章九:GDD消息系统 gd信息
- 2024-12-24 Qt设备识别(简单的密钥生成器) qt设备管理系统
- 2024-12-24 Access开发的《财务经济管理系统》
- 2024-12-24 初级开发人员告诉我:OO 设计模式太复杂而且没用
- 2024-12-24 从零开始学Qt(89):UDP单播和广播
- 2024-12-24 Qt入门阶段之事件 qtc间期延长的临床意义
- 2024-12-24 Access窗体查询制作步骤第二课 access窗体怎么做查询按钮
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)