QT 图形视图框架
https://blog.csdn.net/qq769651718/article/details/79357936
使用QPushButton、QLabel、QCheckBox等构成GUI的控件或自定义图形时,开发应用程序会变得很简单。
但是如果想在GUI中使用数十个或者数百个图形对象,向用户完美展示控制场景,则会受到很多的限制。
图形视图框架用来管理2D图形项,支持绘制、缩放、事件响应等等。
1、快速提供并管理大量对象
2、将事件传递到每一个对象
3、管理焦点处理或对象选择等状态
图形视图框架是按照MVC设计模式绘图, MVC设计模式包括三个元素:数据的模型(Model),用户界面的视图(View) ,用户再界面上的操作控制Controller。
QGraphicsView
QGraphicsView 是为了在场景上显示图元而提供的类。QGraphicsView包括可视控件区域和用于显示大场景滚动区域,可以接受用户输入事件。QGraphicsView间接继承至QWidget。
QGraphicsScene
QGraphicsScene类可以保存图元,也可以处理用户输入事件。是图形对象QGraphicsItem的容器,为管理大量的items提供一个快速的接口。QGraphicsScene只继承自QObject,所以本身是不可见的,必须通过与之相连的视图类QGraphicsView来显示.
QGraphicsItem
QGraphicsItem是为了在图形视图上实现图形对象而提供的类。支持鼠标、键盘、焦点事件,支持拖放,在它的基础上可以继承出各种图元类。支持碰撞检测collision detection.
1 QGraphicsScene的常用函数
常用添加图元函数
QGraphicsScene::setBackgroundBrush //填充背景色
QGraphicsScene::setForegroundBrush //填充前景色
QGraphicsScene::addSimpleText //添加简单文本
QGraphicsScene::addLine //添加直线
QGraphicsScene::addRect //添加矩形
QGraphicsScene::addEllipse //添加椭圆
QGraphicsScene::addWidget //添加窗口
QGraphicsScene::addPixmap //添加图片
例如:
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QLabel>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
/*设置场景的背景色前景色*/
scene.setBackgroundBrush(QBrush(Qt::red));
scene.setForegroundBrush(QBrush(QColor(0, 255, 0, 50)));
/*添加线*/
scene.addLine(0, 0, 100, 100, QPen(Qt::black));
/*添加矩形*/
scene.addRect(0, 100, 100, 100, QPen(Qt::yellow), QBrush(Qt::blue));
/*添加椭圆*/
scene.addEllipse(100, 0, 100, 100, QPen(Qt::red), QBrush(Qt::green));
/*添加简单文本,并且设置文本字体,并且描边*/
scene.addSimpleText("hello", QFont("system", 40))
->setPen(QPen(QBrush(Qt::yellow), 3));
/*添加图片,并且移动位置*/
scene.addPixmap(QPixmap("E:\\qt_workspace\\pic\\wallet.png"))
->setPos(200, 200);
/*添加一个窗口*/
QLabel label("widget");
scene.addWidget(&label);
return app.exec();
}
操作图元函数
QGraphicsScene::itemAt //查找场景某个中最表层的item
QGraphicsScene::setSelectionArea //设置选定区域
QGraphicsScene::setSceneRect //设置场景的区域大小
QGraphicsScene::itemsBoundingRect //根据所有的item计算区域大小
QGraphicsScene:: selectedItems //获取被选中的item,item必须为可选QGraphicsItem::ItemIsSelectable
2 QGraphicsItem的常用函数
QGraphicsItem::rect //不带边框的图形区域
QGraphicsItem::boundingRect //带边框的图形区域
QGraphicsItem::collidesWithItem //碰撞检测
QGraphicsItem::setScale //缩放
QGraphicsItem::setRotation //旋转
QGraphicsItem::setZValue //设置z坐标,图元的叠加先后顺序可以用它来设置
QGraphicsItem::setPos //设置位置坐标
设置item的属性
void QGraphicsItem::setFlags(GraphicsItemFlags flags);
/*
*参数GraphicsItemFlags flags 为枚举类型,可以以下值
* QGraphicsItem::ItemIsMovable 是否可以移动
* QGraphicsItem::ItemIsSelectable 是否可以被选中
* QGraphicsItem::ItemIsFocusable 是否可以设置为焦点item
*/
3 图形视图的坐标系
3.1 QGraphscItem图元坐标系
图元对象都有自身的坐标系,坐标系以(0,0)为坐标原点,自左向右递增是x轴,自上而下递增是y轴,而且所有图元对象的移动转换作用点都是(0, 0),坐标值可以是浮点型数值。
3.2 QGraphicsScene场景坐标系
场景坐标系是所有图元对象的绝对坐标. 有四个象限。坐标系以(0,0)为坐标原点,自左向右递增是x轴,自上而下递增是y轴,坐标值可以是浮点型数值。
3.3 QGraphicsView视图坐标系
视图坐标是窗口坐标。视图中的坐标单位1个像素。
3.4 坐标映射
父子图元坐标映射
QGraphicsItem::mapToParent //子图元坐标映射到父图元
QGraphicsItem::mapFromParent //父图元坐标映射到子图元
图元与场景坐标映射
QGraphicsItem::mapToScene //图元到场景
QGraphicsItem::mapFromScene //场景到图元
场景与视图坐标映射
QGraphicsView::mapFromScene //场景到视图
QGraphicsView::mapToScene //视图到场景
3.5 调整坐标系
调整坐标系的的类是QTransform、QMatrix,这两个类都提供了缩放、旋转、变形坐标系的方法。
3.5.1 调整QGraphicsVeiw坐标系
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QLabel>
#include <QTransform>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
QTransform transform;
//transform.translate(100, 0); //移动坐标原点
transform.scale(1.5, 1); //缩放
//transform.rotate(10); //旋转
// transform.shear(0.1, 0.1); //变形
view.setTransform(transform);
/*添加矩形*/
scene.addRect(0, 100, 100, 100, QPen(Qt::yellow), QBrush(Qt::blue));
return app.exec();
}
3.5.2 调整QGraphicsItem坐标系
#include <QApplication>
#include <QGraphicsView>
#include <QTransform>
#include <QGraphicsRectItem>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
QTransform transform;
//transform.translate(100, 0); //移动坐标原点
transform.scale(1.5, 1); //缩放
//transform.rotate(10); //旋转
// transform.shear(0.1, 0.1); //变形
/*添加矩形*/
QGraphicsRectItem *rect = scene.addRect(0, 100, 100, 100
, QPen(Qt::yellow), QBrush(Qt::blue));
rect->setTransform(transform);
return app.exec();
}
4 图形视图的事件处理
QGraphicsView是窗口类,那么它当然可以处理鼠标、键盘等事件。QGraphicsScene
不是窗口类,但是它也能处理鼠标、键盘等窗口类的事件。
QGraphicsView收到event,就会转换成QGraphicsScene的事件,QGraphicsScene对象再传递给对应的QGraphicsItem。
4.1 QGraphicsView的事件处理
QGraphicsView的事件处理机制与普通的QWidget相同。
#include "widget.h"
#include <QDebug>
GraphicsView::GraphicsView(QWidget *parent)
: QGraphicsView(parent)
{
}
void GraphicsView::mousePressEvent(QMouseEvent* ev)
{
qDebug() << "GraphicsView" << __FUNCTION__ << endl;
/*必须传递到基类的mousePressEvent,否则QGraphicsScene无法收到消息*/
QGraphicsView::mousePressEvent(ev);
}
GraphicsView::~GraphicsView()
{
}
4.2 QGraphicsScene的事件处理
QGraphicsScene的事件处理机制与QWidget不同, 使用QGraphicsSceneEvent来传递事件。
例如,鼠标点击事件的虚函数为:
[virtual protected] void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
scene.cpp
#include "scene.h"
#include <QDebug>
MyScene::MyScene(QObject * parent) : QGraphicsScene(parent)
{
}
void MyScene::mousePressEvent(QGraphicsSceneMouseEvent* ev)
{
qDebug() << "GraphicsScene" << __FUNCTION__ << endl;
/*必须传递到基类的mousePressEvent中,否则QGraphicsItem无法收到消息*/
QGraphicsScene::mousePressEvent(ev);
}
4.3 QGraphicsItem的事件处理
QGraphicsItem的事件处理函数传递事件也是使用的QGraphicsSceneEvent。
常用的事件处理函数有:
//鼠标按下事件,场景上面的鼠标事件的触发位置坐标需要使用mouseEvent->scenePos()来获取
[virtual protected] void QGraphicsScene::mousePressEvent(
QGraphicsSceneMouseEvent *mouseEvent)
//鼠标释放事件
[virtual protected] void QGraphicsScene::mouseReleaseEvent(
QGraphicsSceneMouseEvent *mouseEvent)
//鼠标移动事件
[virtual protected] void QGraphicsScene::mouseMoveEvent(
QGraphicsSceneMouseEvent *mouseEvent)
//鼠标滚轮事件
[virtual protected] void QGraphicsScene::wheelEvent(
QGraphicsSceneWheelEvent *wheelEvent)
/*注意:先使用void QGraphicsItem::setAcceptHoverEvents(bool enabled),才能接收到hoverevent*/
//鼠标进入事件
[virtual protected] void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
//鼠标离开事件
[virtual protected] void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
//鼠标不点击移动事件
[virtual protected] void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
/*键盘按下事件 setFlags(QGraphicsItem::ItemIsFocusable); 再调用setFocus才能接受键盘事件*/
[virtual protected] void QGraphicsItem::keyPressEvent(QKeyEvent *event)
//键盘释放事件
[virtual protected] void QGraphicsItem::keyReleaseEvent(QKeyEvent *event)
//绘画事件
[pure virtual] void QGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR)
5 图形视图的内存管理
QGraphicsView通过指定父窗口托管内存, QGraphicsScene通过指定父QObject对象托管内存。QGraphicsItem 通过指定父QGraphicsItem对象托管内存, 顶级QGraphicsItem对象通过QGraphicsScene对象托管。
6 图形视图碰撞检测
所谓的碰撞检测,就是判断某个点是否在图元对象中,或者两个图元是否有接触。
//判断QGraphicsItem坐标系中某点, 是否包含在QGraphicsItem中,需要将点转换成QGraphicsItem坐标
QGraphicsItem::contains()
//item的矩形边框
QGraphicsItem::boundingRect()
//返回item的形状path,可以是任何形状。
QGraphicsItem::shape()
//判断是否与某个item碰撞
QGraphicsItem::collidesWithItem
QGraphicsScene认为所有图元的boundingRect函数与shape函数都是不发生改变的,除非用户进行通知。
如果你想改变一个图元的范围,必需先调用prepareGeometryChange以允许QGraphicsScene进行更新。
7 背景缓冲
如果场景的背景需要大量耗时的渲染,可以利用背景缓存,当下次需要渲染背景时,可以快速进行渲染。它的原理就是,把整个视口先绘制到一个QPixmap上。
但是这个只适合较小的视口,也就是说,如果视图窗口很大,而且有滚动条,那么就不再适合缓存背景。
我们可以使用setCacheMode(QGraphicsView::CacheBackground)来设置背景缓存,默认设置是没有缓存QGraphicsView::CacheNone。
void QGraphicsView::setCacheMode(CacheMode mode);
8 打印QGraphicsScene
将整个场景打印到一个QPainterDevice的派生类对象中,例如QPixmap。
main.cpp
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
scene.addRect(0, 0, 100, 100, QPen(Qt::red), QBrush(Qt::yellow));
QPixmap pixmap(scene.sceneRect().width(), scene.sceneRect().height());
pixmap.fill(QColor(0, 0, 0, 0));
QPainter painter;
painter.begin(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
scene.render(&painter);
painter.end();
pixmap.save("d:\\123.png");
return app.exec();
}
9 图形效果叠加
Qt中可以给图元添加特效,QGraphicsEffect为特效基本类。
有以下具体特效
QGraphicsBlurEffect //模糊效果
QGraphicsDropShadowEffect //阴影效果
QGraphicsColorizeEffect //使用色调的着色效果
QGraphicsOpacityEffect //透明效果
例如:main.cpp
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QGraphicsBlurEffect>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
QGraphicsBlurEffect effect;
effect.setBlurRadius(10);
QGraphicsRectItem* rect = scene.addRect(0, 0, 100, 100, QPen(Qt::red), QBrush(Qt::yellow));
rect->setGraphicsEffect(&effect);
return app.exec();
}
---------------------
作者:吓人的猿
来源:CSDN
原文:https://blog.csdn.net/qq769651718/article/details/79357936
版权声明:本文为博主原创文章,转载请附上博文链接!
QT 图形视图框架的更多相关文章
- Qt图形视图框架公开课资料
接受CSDN学院的邀请,讲一次公开课,主题是Qt图形视图框架,报名链接在这里:http://edu.csdn.net/huiyiCourse/detail/228. 内容有两部分:自定义Item和拖放 ...
- 用Qt图形视图框架开发拼图游戏
用Qt的图形视图框架(Graphics View Framework)做了一个拼图游戏DEMO,演示了: QGraphicsView.QGraphicsScene.QGraphicsItem的基本用法 ...
- Qt 2D绘图之五:图形视图框架的结构和坐标系统
一.图形视图框架的结构 在前面讲的基本绘图中,我们可以自己绘制各种图形,并且控制它们.但是,如果需要同时绘制很多个相同或不同的图形,并且要控制它们的移动.检测它们的碰撞和叠加:或者我们想让自己绘制的图 ...
- Qt开发技术:图形视图框架(一)基本介绍
前话 使用到Qt的视图框架. Qt视图框架介绍 简介 图形视图框架(The Graphic View Framework)用于管理和与大量定制的二维图形项目交互,以及用于可视化项目的视图小 ...
- Qt-MVC图形视图框架分解
前面在<Qt-MVC图形视图框架出识>中我们了解了Qt图形视图框架中三个最基本的类,弄清他们的关系,本片小文,我们将对QGraphicsView,QGraphiceScene,QGraph ...
- Qt-MVC图形视图框架初识
使用QPushButton.QLabel.QCheckBox等构成GUI的控件或自定义图形时,开发应用程序会变得很简单.但是如果想在GUI中使用数十个或者数百个图形对象,向用户完美展示控制场景,则会受 ...
- Qt之图形视图框架
简述 图形视图(Graphics View)提供了一个平台,用于大量自定义2D图元的管理与交互,并提供了一个视图部件(view widget)来显示可以缩放和旋转的图元. 框架包括一个事件传播架构,支 ...
- Qt 2D绘图之六:图形视图框架的事件处理与传播
一.简介 图形视图框架中的事件都是首先由视图进行接收,然后传递给场景,再由场景传递给相应的图形项.而对于键盘事件,它会传递给获得焦点的图形项,可以使用QGraphicsScene类的setFocusI ...
- Qt开发技术:图形视图框架(二)场景QGraphicsScene、QGraphicsItem与QGraphicsView详解
前话 Qt的图形视图框架,最核心的三个类为:QGraphicsScene.QGraphicsItem与QGraphicsView. 基于图形框架的高级白板软件Demo QGraphicsSce ...
随机推荐
- 洛谷 - UVA11346 - 概率 Probability - 积分
要是没学过高等数学的积分怎么办呢?可以求助于自适应辛普森法. 容易发现其实这个图形是对称的,我们只要求第一象限就可以了,第一象限如上图. 由于取点是在面积内等概率的,由高中的几何概型可知,所求概率为: ...
- L2-024 部落 (25 分)并查集
在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈.我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同 ...
- hoj2798 Globulous Gumdrops
Globulous Gumdrops My Tags (Edit) Source : 2008 Stanford Programming Contest Time limit : 1 se ...
- Ruby对象模型总结
参考<Ruby元编程>,元编程,即 用来编写代码的代码 . 对象由一组实例变量和一个类的引用组成 对象的方法存在与对象所属的类中,类似js中的prototype,在ruby中准确的说,应该 ...
- IT兄弟连 JavaWeb教程 JSP经典面试题
1.JSP标准提供了三种独立的向JSP添加Java代码的技术,请列举. <% %>JSP程序代码块,内部可以直接嵌入Java代码. <%! %>JSP声明区,内部可以声明变量和 ...
- js对象—类型和属性特性
前言 权威指南中摘要的,工作中用不到的,重要的js基础. 三类对象两类属性 内置对象(native object) 是由ECMScript规范定义的对象或者类.例如:函数,数组,日期,正则... 宿主 ...
- extern使用方法总结!(转)
extern 在源文件A里定义的函数,在其它源文件里是看不见的(即不能访问).为了在源文件B里能调用这个函数,应该在B的头部加上一个外部声明: extern 函数原型: 这样,在源文件B里也可以调 ...
- cdq(2018.10.18)
一句话题意:给你三个数列{a_i},{b_i},{c_i},保证每个数列都恰好是一个排列.你需要求出满足\(a_i<a_j,b_i<b_j,c_i<c_j\)的有序对\((i,j)\ ...
- 一篇文章彻底弄懂CAS实现SSO单点登录原理
1. CAS 简介 1.1. What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨在为 Web ...
- 问题: 查看某个文件的修改记录| git log 高级用法
参考文章: git查看某个文件的修改历史 5.3 Git log 高级用法 基本步骤 git log --pretty=oneline [文件名] git show [节点] git log 两周高级 ...