由于项目要求,需要加载svg格式图片和pixmap图片,并根据指定坐标在图上进行勾画,并且对相应位置接收鼠标事件。

-继承QGraphicsObject,实现加载pixmap的项

myimageitem.h

#ifndef MYIMAGEITEM_H
#define MYIMAGEITEM_H
#include <QGraphicsObject>
#include <QPainter>
#include <QVector>
#include <QGraphicsSceneMouseEvent>
#include <QMap> class myimageitem: public QGraphicsObject
{
Q_OBJECT
public:
myimageitem(QRectF, rect,const QPixmap &image,QGraphicsObject *parent = nullptr);//rect 项的边框尺寸,image 图像
~myimageitem(); void setRect(const QRectF &rect); QRectF boundingRect()const override;
void paint(QPainter *panter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
public slots:
void onSyn(int id); signals:
void syn(int id);
private:
QRectF m_rect;
QPixmap m_pixmap;
float deltaX; // 显示窗口大小与实际图片横轴比例
float deltaY; // 显示窗口大小与实际图片竖轴比例
QMap<int, bool> _rectPointSelected;// 标记矩形是否被鼠标事件选中
QMap<int,QRectF> _rectPoint; // 保存矩形数据
}; #endif // MYIMAGEITEM_H
#include "myimageitem.h"

myimageitem::myimageitem(QRectF rect,const QPixmap &image, QGraphicsObject * parent):QGraphicsObject(parent),m_pixmap(image)
{
deltaX = rect.width()/m_pixmap.width();
deltaY = rect.height()/m_pixmap.height();
QRectF rect1(0,0,200*deltaX,200*deltaY);
QRectF rect2(200*deltaX, 200*deltaY, 200*deltaX, 200*deltaY);

  // 初始化测试坐标数据
_rectPoint.insert(0, rect1);
_rectPointSelected.insert(0,false);
_rectPoint.insert(1,rect2);
_rectPointSelected.insert(1,false);
setRect(rect);
}
myimageitem::~myimageitem(){ } void myimageitem::setRect(const QRectF &rect)
{
if(m_rect == rect){
return;
}
prepareGeometryChange();
m_rect = rect;
update(); // 通知重绘图片 } QRectF myimageitem::boundingRect() const{
return m_rect; // 边界尺寸
} void myimageitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
Q_UNUSED(option);
Q_UNUSED(widget); painter->setRenderHint(QPainter::Antialiasing, true); // 打开抗锯齿
painter->save();
painter->drawPixmap(m_rect, m_pixmap,QRectF()); // 画图 for(QMap<int, bool>::iterator it = _rectPointSelected.begin(); it != _rectPointSelected.end(); ++it){
if(!it.value()){
painter->setPen(Qt::blue); // 如果未被选中
}else {
painter->setPen(Qt::red); // 如果被选中
it.value() = false; // 重绘之后选中状态重置
}
painter->drawRect(_rectPoint[it.key()]); // 绘制矩形
} painter->restore();
} void myimageitem::mousePressEvent(QGraphicsSceneMouseEvent *event){ // 接收鼠标事件
if(event->button() == Qt::LeftButton){
for(QMap<int, QRectF>::iterator it = _rectPoint.begin(); it != _rectPoint.end(); ++it){
if(it.value().contains(event->pos())){
prepareGeometryChange();// 保持项的索引,即使改变了项的尺寸,如果有必要会调用update()
_rectPointSelected[it.key()] = true; // 选中矩形
// emit syn(it.key());
}
}
}
} void myimageitem::onSyn(int id){
prepareGeometryChange();
_rectPointSelected[id] = true;
update();
}

-继承QGraphicsSvgItem

mygriditem.h

#ifndef MYGRIDITEM_H
#define MYGRIDITEM_H
#include <QtSvg/QGraphicsSvgItem>
#include <QGraphicsSceneMouseEvent>
#include <QtSvg/QSvgRenderer>
#include <QPainter> class mygriditem :public QGraphicsSvgItem
{
Q_OBJECTpublic:
mygriditem(QRectF boundRect,const QString &svgFile,const QSize svgSize,QGraphicsSvgItem *parent = nullptr);// 导入svg格式图片文件 和尺寸
~mygriditem();
QRectF boundingRect()const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)override; signals:
void syn(int id);
public slots:
void onSyn(int id); protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
private:
QRectF _boundRect; // 边界矩形

QSvgRenderer *_svgRender;
float _xDelta;
float _yDelta;
QMap<int, bool> _rectPointSelected;
QMap<int,QRectF> _rectPoint;
}; #endif // MYGRIDITEM_H
#include "mygriditem.h"

mygriditem::mygriditem(QRectF boundRect,const QString &svgFile,const QSize svgSize ,QGraphicsSvgItem *parent):QGraphicsSvgItem(parent),
_boundRect(boundRect)
{
_svgRender = new QSvgRenderer(svgFile); //加载svg图 _xDelta = _boundRect.width()/svgSize.width();
_yDelta = _boundRect.height()/ svgSize.height(); QRectF rect1(0*_xDelta,0*_yDelta,60*_xDelta,60*_yDelta);
QRectF rect2(60*_xDelta,60*_yDelta,60*_xDelta,60*_yDelta);
_rectPoint.insert(0, rect1);
_rectPoint.insert(1 ,rect2);
_rectPointSelected.insert(0, false);
_rectPointSelected.insert(1, false);
} mygriditem::~mygriditem(){ } void mygriditem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setRenderHint(QPainter::Antialiasing, true);
painter->save();
_svgRender->render(painter, _boundRect); // 绘制svg图片
// QGraphicsSvgItem::paint(painter, option, widget);
for(QMap<int,bool>::iterator it = _rectPointSelected.begin(); it != _rectPointSelected.end() ;++it){
if(it.value()){
painter->setPen(Qt::red);
it.value() = false;
}else {
painter->setPen(Qt::green);
}
painter->setBrush(Qt::green);
painter->drawRect(_rectPoint[it.key()]);
}
painter->restore();
} QRectF mygriditem::boundingRect() const{
return _boundRect;
} void mygriditem::mousePressEvent(QGraphicsSceneMouseEvent *event){
if(event->button() == Qt::LeftButton){
for(QMap<int, QRectF>::iterator it = _rectPoint.begin(); it != _rectPoint.end(); ++ it){
if(it.value().contains(event->pos())){
prepareGeometryChange();
_rectPointSelected[it.key()] = true;
update();
// emit syn(it.key());
}
}
}
}
void mygriditem::onSyn(int id){
prepareGeometryChange();
_rectPointSelected[id] = true;
update();
}

-继承QGraphicsView 实现缩放 拖拽(这部分参考其它博主)

mygraphicsview.h

#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H #include <QGraphicsView>
#include <QKeyEvent> class mygraphicsview:public QGraphicsView
{
public:
explicit mygraphicsview(QWidget *parent = nullptr);
~mygraphicsview(); // 平移速度
void setTranslateSpeed(qreal speed);
qreal translateSpeed() const; // 缩放的增量
void setZoomDelta(qreal delta);
qreal zoomDelta() const;
protected:
// 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
// 平移
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
// 放大/缩小
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; public Q_SLOTS:
void zoomIn(); // 放大
void zoomOut(); // 缩小
void zoom(float scaleFactor); // 缩放 - scaleFactor缩放的比例因子
void translate(QPointF delta); // 平移 private:
Qt::MouseButton m_translateButton; // 平移按钮
qreal m_translateSpeed; // 平移速度
qreal m_zoomDelta; // 缩放的增量
bool m_bMouseTranslate; // 平移标识
QPoint m_lastMousePos; // 鼠标最后按下的位置
qreal m_scale; // 缩放值
}; #endif // MYGRAPHICSVIEW_H
#include "mygraphicsview.h"

#define VIEW_CENTER viewport()->rect().center()
#define VIEW_WIDTH viewport()->rect().width()
#define VIEW_HEIGHT viewport()->rect().height() mygraphicsview::mygraphicsview(QWidget *parent):QGraphicsView(parent),
m_translateButton(Qt::LeftButton),
m_scale(1.0),
m_zoomDelta(0.1),
m_translateSpeed(1.0),
m_bMouseTranslate(false)
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setCursor(Qt::PointingHandCursor);
setRenderHint(QPainter::Antialiasing); // setSceneRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
// setSceneRect(0,0,5472, 3648);
// centerOn(0, 0); } mygraphicsview::~mygraphicsview(){ } // 平移速度
void mygraphicsview::setTranslateSpeed(qreal speed)
{
// 建议速度范围
Q_ASSERT_X(speed >= 0.0 && speed <= 2.0,
"InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0].");
m_translateSpeed = speed;
} qreal mygraphicsview::translateSpeed() const
{
return m_translateSpeed;
} // 缩放的增量
void mygraphicsview::setZoomDelta(qreal delta)
{
// 建议增量范围
Q_ASSERT_X(delta >= 0.0 && delta <= 1.0,
"InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0].");
m_zoomDelta = delta;
} qreal mygraphicsview::zoomDelta() const
{
return m_zoomDelta;
} // 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转
void mygraphicsview::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Up:
translate(QPointF(0, -2)); // 上移
break;
case Qt::Key_Down:
translate(QPointF(0, 2)); // 下移
break;
case Qt::Key_Left:
translate(QPointF(-2, 0)); // 左移
break;
case Qt::Key_Right:
translate(QPointF(2, 0)); // 右移
break;
case Qt::Key_Plus: // 放大
zoomIn();
break;
case Qt::Key_Minus: // 缩小
zoomOut();
break;
case Qt::Key_Space: // 逆时针旋转
rotate(-5);
break;
case Qt::Key_Enter: // 顺时针旋转
case Qt::Key_Return:
rotate(5);
break;
default:
QGraphicsView::keyPressEvent(event);
}
} // 平移
void mygraphicsview::mouseMoveEvent(QMouseEvent *event)
{
if (m_bMouseTranslate){
QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos);
translate(mouseDelta);
} m_lastMousePos = event->pos(); QGraphicsView::mouseMoveEvent(event);
} void mygraphicsview::mousePressEvent(QMouseEvent *event)
{
if (event->button() == m_translateButton) {
// 当光标底下没有 item 时才能移动
QPointF point = mapToScene(event->pos());
if (scene()->itemAt(point, transform()) != NULL) {
m_bMouseTranslate = true;
m_lastMousePos = event->pos();
}
} QGraphicsView::mousePressEvent(event);
} void mygraphicsview::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == m_translateButton)
m_bMouseTranslate = false; QGraphicsView::mouseReleaseEvent(event);
} // 放大/缩小
void mygraphicsview::wheelEvent(QWheelEvent *event)
{
// 滚轮的滚动量
QPoint scrollAmount = event->angleDelta();
// 正值表示滚轮远离使用者放大负值表示朝向使用者缩小
scrollAmount.y() > 0 ? zoomIn() : zoomOut();
} // 放大
void mygraphicsview::zoomIn()
{
zoom(1 + m_zoomDelta);
} // 缩小
void mygraphicsview::zoomOut()
{
zoom(1 - m_zoomDelta);
} // 缩放 - scaleFactor缩放的比例因子
void mygraphicsview::zoom(float scaleFactor)
{
// 防止过小或过大
qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
if (factor < 0.5 || factor > 100)
return; scale(scaleFactor, scaleFactor);
m_scale *= scaleFactor;
} // 平移
void mygraphicsview::translate(QPointF delta)
{
// 根据当前 zoom 缩放平移数
delta *= m_scale;
delta *= m_translateSpeed; // view 根据鼠标下的点作为锚点来定位 scene
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
QPoint newCenter(VIEW_WIDTH / 2 - delta.x(), VIEW_HEIGHT / 2 - delta.y());
centerOn(mapToScene(newCenter)); // scene 在 view 的中心点作为锚点
setTransformationAnchor(QGraphicsView::AnchorViewCenter);
}

-测试代码

cview.h

#ifndef CVIEW_H
#define CVIEW_H #include <QWidget>
#include <QGraphicsScene>
#include <QtSvg/QSvgRenderer>
#include <QtSvg/QGraphicsSvgItem>
#include<QGraphicsGridLayout>
#include <QGraphicsLayout>
#include "mygraphicsview.h"
#include "myimageitem.h"
#include "mygriditem.h" QT_BEGIN_NAMESPACE
namespace Ui { class CView; }
QT_END_NAMESPACE class CView : public QWidget
{
Q_OBJECT public:
CView(QWidget *parent = nullptr);
~CView(); private:
Ui::CView *ui;
QGraphicsScene *_scene;
QGraphicsObject *_codeImgae;
};
#endif // CVIEW_H
#include "cview.h"
#include "./ui_cview.h" CView::CView(QWidget *parent)
: QWidget(parent),
ui(new Ui::CView),
_scene(new QGraphicsScene) {
ui->setupUi(this);
QPixmap pixmap;
pixmap.load("XXX.png"); // 传入自己的图片
float pixWidth = pixmap.width();
float pixHeight = pixmap.height();
float deltaX = ui->graphicsView_2->width()/pixWidth;
float deltaY = ui->graphicsView_2->height()/pixHeight; int viewW = ui->graphicsView_2->width();
int viewH = ui->graphicsView_2->height(); _codeImgae = new myimageitem(QRectF(0, 0,viewH, viewH),pixmap);
_scene->addItem(_codeImgae);
ui->graphicsView_2->setScene(_scene);
float w = ui->graphicsView->width();
float h = ui->graphicsView->height();
mygriditem *svg_render = new mygriditem(QRectF(0,0,w,h),QString("XXX.svg"));// 传入自己的图片
QGraphicsScene *svgScene = new QGraphicsScene(); svgScene->addItem(svg_render); QList<QGraphicsItem*> items = svgScene->items();
ui->graphicsView->setScene(svgScene);
} CView::~CView()
{
delete ui;
}

QGraphicsView, QGraphicsObject ,QQGraphicsSvgItem 图片接收鼠标事件 拖拉 收放的更多相关文章

  1. 关于CMainFrm不接收鼠标事件响应原因

    CMainFrm即主框架窗口对鼠标的左键和右键在OnLButtonDown中无响应 解决方案: 1.在OnNcLButtonDown中响应.(即非客户区中响应) 参考文献:http://www.cod ...

  2. WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件

    在WPF中,只有鼠标位置在某个控件上的时候才会触发该控件的鼠标事件.例如,有两个控件都注册了MouseDown和MouseUp事件,在控件1上按下鼠标,不要放开,移动到控件2上再放开.在这个过程中,控 ...

  3. js 鼠标事件的抓取代码

    js 鼠标事件的抓取代码,分享给大家. 1.通过ele.setCapture();设置鼠标事件的抓取. 2,应用可以通过单.双击文字来获取时间. <html> <head> & ...

  4. QT学习笔记5:QMouseEvent鼠标事件简介

    一.QMouseEvent的详细描述 首先请注意,Qt中的QMouseEvent一般只涉及鼠标左键或右键的单击.释放等操作,而对鼠标滚轮的响应则通过QWheeEvent来处理. QMouseEvent ...

  5. Qt事件系统之二:鼠标事件和滚轮事件

    在Qt中,事件作为一个对象,继承自 QEvent 类,常见的有键盘事件 QKeyEvent.鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等,与 QEvent 类的继承关系图 ...

  6. 2017年10月21日 CSS常用样式&鼠标样式 以及 jQuery鼠标事件& jQuery图片轮播& jQuery图片自动轮播代码

    css代码 背景与前景 background-color:#0000; //背景色,样式表优先级高 background-image:url(路径); //设置背景图片 background-atta ...

  7. 模拟拖拽图片 碰撞检测 DOM 鼠标事件 闭包

    <!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...

  8. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  9. 前端(十五)—— JavaScript事件:绑定事件方式、事件的冒泡和默认事件、鼠标事件、键盘事件、表单 事件、文档事件、图片事件、页面事件

    JS事件:绑定事件方式.事件的冒泡和默认事件.鼠标事件.键盘事件.表单 事件.文档事件.图片事件.页面事件 一.事件的两种绑定方式 1.on事件绑定方式 document.onclick = func ...

随机推荐

  1. 死磕Java面试系列:深拷贝与浅拷贝的实现原理

    深拷贝与浅拷贝的问题,也是面试中的常客.虽然大家都知道两者表现形式不同点在哪里,但是很少去深究其底层原理,也不知道怎么才能优雅的实现一个深拷贝.其实工作中也常常需要实现深拷贝,今天一灯就带大家一块深入 ...

  2. Go语言正/反向代理的姿势

    先重温一下什么叫反向代理,正向代理. 鹅厂二面,nginx回忆录 所谓正向,反向代理取决于代理的是出站请求,还是入站请求. 正向代理: 代理的出站请求, 客户端能感知到代理程序,架构上距离客户端更近. ...

  3. 更改安装Oracle数据库时设定的System sys等用户的密码

    因本地Oracle数据库安装久远,不知道连接账号密码,查阅了一些资料最终修改成功,Mark up! 1 在开始菜单找到Oracle服务,打开SQL plus 2 输入命令连接到数据库并修改部分用户密码 ...

  4. 关于Docker的一些事--Docker概述

    为什么会出现docker? 背景 以一个食品工厂为例子,有一款食品产品,从研发到包装,需要分别两套生产线,虽然感觉说很好,符合SOP,但是吧,产能很慢,这是为什么呢? 研发:食品搭配.颜色搭配.荤素搭 ...

  5. HTTPS详解二

    前言 在上篇文章中,我已经为大家介绍了 HTTPS 的详细原理和通信流程,但总感觉少了点什么,应该是少了对安全层的针对性介绍,那么这篇文章就算是对HTTPS 详解一的补充吧.还记得这张图吧. HTTP ...

  6. Go语言核心36讲11

    至今为止,我们讲过的集合类的高级数据类型都属于针对单一元素的容器. 它们或用连续存储,或用互存指针的方式收纳元素,这里的每个元素都代表了一个从属某一类型的独立值. 我们今天要讲的字典(map)却不同, ...

  7. selenium被某些网页检测不允许正常访问、登录等,解决办法

    网站通过什么方式检测 function b() { return "$cdc_asdjflasutopfhvcZLmcfl_"in u || d.webdriver } 通过上方的 ...

  8. day08 final关键字&面向对象——多态&抽象类、方法&向上、向下转型

    day08 final关键字 最终的不可更改的 特点: 1)修饰类,类不能被继承 2)修饰方法,方法不能被重写 3)修饰成员变量(变为常量),值不能修改,名字大写,声明同时给常量赋值 main方法中 ...

  9. WEB入门——信息搜集1-20

    WEB1--查看源码 查看源码即可得flag. WEB2--JS前端禁用 查看源码即可得flag. JavaScript实现禁用的方法简单来说就是当用户使用键盘执行某一命令是返回的一种状态,而这种状态 ...

  10. Guava LoadingCache本地缓存的正确使用姿势——异步加载

    1. [背景]AB实验SDK耗时过高 同事在使用我写的实验平台sdk之后,吐槽耗时太高,获取实验数据分流耗时达到700ms,严重影响了主业务流程的执行 2. [分析]缓存为何不管用 我记得之前在sdk ...