目录名字

  • Qt 视图框架示例 Colliding Mice 的翻译
    • 简介:
    • Mouse Class 定义
    • Mouse Class 定义
    • The Main() 函数

Qt 视图框架示例 Colliding Mice 的翻译

简介:

该示例程序介绍了怎样在Qt的视图框架里创建动画以及冲突检测。

视图框架提供了QGraphicsScene class 场景类来管理2D图形对象.一个QGraphicsView widget 来是显示这些图形项,并且支持视图的缩放和旋转。

在该示例中, Mouse class 自定义了一些Mice 的图形项,main() 函数提供了应用程序的窗体。

首先我们来学习Mouse 类是如何实现动画和冲突检测的。然后我们学习main()函数是如何将mice 图形项添加到场景中。

Mouse Class 定义

The mouse class继承自QGraphicsItem. QGraphicsItem是视图框架中所有图形项的基类。它提供了一个轻量级的框架来创建用户自定义的一些图形项。

  class Mouse : public QGraphicsItem{public:Mouse();QRectF boundingRect() const override;QPainterPath shape() const override;void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) override;protected:void advance(int step) override;private:qreal angle = 0;qreal speed = 0;qreal mouseEyeDirection = 0;QColor color;};

当我们创建自定义图形项的时候,我们必须要重写两个虚函数
1、 boundingRect(), 绘图的边界
2、 paint(), 绘图

我们还重写了两个函数shape()和advance().
1、shape():mice 图形项的准确形状。默认情况下,返回的是bounding rectangle.
2、advance():实现动画

Mouse Class 定义

构造函数:初始化一些私有变量

  Mouse::Mouse() : color(QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256),QRandomGenerator::global()->bounded(256)){setRotation(QRandomGenerator::global()->bounded(360 * 16));}

这里我们用QRandomGenerator. 来实现Mice的不同肤色。
setRotation()来改变Mice 的方向。

QGraphicsScene 会在帧的推进中会调用每一图形项的advance()功能,这里我们重写了这个advance()方法,于是Mice会 一帧帧的动起来了。

  void Mouse::advance(int step){if (!step)return;QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));if (lineToCenter.length() > 150) {qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);if (angleToCenter < Pi && angleToCenter > Pi / 4) {// Rotate leftangle += (angle < -Pi / 2) ? 0.25 : -0.25;} else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) {// Rotate rightangle += (angle < Pi / 2) ? 0.25 : -0.25;}} else if (::sin(angle) < 0) {angle += 0.25;} else if (::sin(angle) > 0) {angle -= 0.25;}

因为advance()被调用两次,第一次是step=0;然后是step=1;前一次不作任何动作。同时,我们要保证mice待在一个半径是150像素的圆内。

mapFromScene() 是完成从图形项坐标到场景坐标的映射。const QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()<< mapToScene(0, 0)<< mapToScene(-30, -50)<< mapToScene(30, -50));for (const QGraphicsItem *item : dangerMice) {if (item == this)continue;QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);if (angleToMouse >= 0 && angleToMouse < Pi / 2) {// Rotate rightangle += 0.5;} else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) {// Rotate leftangle -= 0.5;}}if (dangerMice.size() > 1 && QRandomGenerator::global()->bounded(10) == 0) {if (QRandomGenerator::global()->bounded(1))angle += QRandomGenerator::global()->bounded(1 / 500.0);elseangle -= QRandomGenerator::global()->bounded(1 / 500.0);}

然后我们要实现老鼠的碰撞的处理

      speed += (-50 + QRandomGenerator::global()->bounded(100)) / 100.0;qreal dx = ::sin(angle) * 10;mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;setRotation(rotation() + dx);setPos(mapToParent(0, -(3 + sin(speed) * 3)));}

最后,我们计算mice的速度,和方向然后设定一个新的坐标。

QGraphicsItem::setPos() 函数会设定一个父窗体的坐标系统的位置。

应为图形项是没有父对象的,所以需要mapToParent() 将坐标映射到需要设置的父窗体的坐标系中。如果没有设定父窗体,默认是映射到场景的坐标系中。

  QRectF Mouse::boundingRect() const{qreal adjust = 0.5;return QRectF(-18 - adjust, -22 - adjust,36 + adjust, 60 + adjust);}

boundingRect() 定义了图形项的矩形边界。Qt中的视图框架是通过该函数的返回值类决定是否需要重画图形项。

  void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *){// Bodypainter->setBrush(color);painter->drawEllipse(-10, -20, 20, 40);// Eyespainter->setBrush(Qt::white);painter->drawEllipse(-10, -17, 8, 8);painter->drawEllipse(2, -17, 8, 8);// Nosepainter->setBrush(Qt::black);painter->drawEllipse(QRectF(-2, -22, 4, 4));// Pupilspainter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4));painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4));// Earspainter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red);painter->drawEllipse(-17, -12, 16, 16);painter->drawEllipse(1, -12, 16, 16);// TailQPainterPath path(QPointF(0, 20));path.cubicTo(-5, 22, -5, 22, 0, 25);path.cubicTo(5, 27, 5, 32, 0, 30);path.cubicTo(-5, 32, -5, 42, 0, 35);painter->setBrush(Qt::NoBrush);painter->drawPath(path);}

paint()函数执行实际的图形项的绘制。绘制时的坐标系都是图形项自身的坐标系。

mice 的耳朵在碰撞是会显示红色。没有碰撞时是灰黑色。

在Qt的视图框架里通过shape-shape 交互来检测识别碰撞冲突,所以shape()函数里返回的shape值必须要准确。

  QPainterPath Mouse::shape() const{QPainterPath path;path.addRect(-10, -20, 20, 40);return path;}

当shapes 变得复杂的时候,shape-shape 重叠检测也会变得复杂,这会耗费计算的时间。重写collidesWithItem()该函数可以自定义冲突的算法。

接着我们来看main()函数

The Main() 函数

 int main(int argc, char **argv){QApplication app(argc, argv);

首先我们创建一个应用程序,并且创建一个场景。

QGraphicsScene scene;
scene.setSceneRect(-300, -300, 600, 600);

QGraphicsScene提供了放置QGraphicsItems 的一个容器。该容器提供了一些函数方法来更好的显示,管理图形项。

当我们创建了一个场景,我们推介设定该场景的大小。若过没有设定大小,场景的大小会随着图形项的增加,而不断增大。

场景会给每一个图形项一个索引号,也可以不设定索引号。索引号可以快速的定位到图形项。

scene.setItemIndexMethod(QGraphicsScene::NoIndex);

QgrapbhicsScene使用下标来高效的管理item的位置,默认的使用BSP树,适用于一个大型的场景,其中的item都是静止不变的,可以选择调用setItemIndexMethod().来禁用下标,可是查看itemIndexMethod来获取更多的信息

  for (int i = 0; i < MouseCount; ++i) {Mouse *mouse = new Mouse;mouse->setPos(::sin((i * 6.28) / MouseCount) * 200,::cos((i * 6.28) / MouseCount) * 200);scene.addItem(mouse);}

//创建mice 图形项

  for (int i = 0; i < MouseCount; ++i) {Mouse *mouse = new Mouse;mouse->setPos(::sin((i * 6.28) / MouseCount) * 200,::cos((i * 6.28) / MouseCount) * 200);scene.addItem(mouse);}

//然后将这些图形项添加到场景中

  QGraphicsView view(&scene);view.setRenderHint(QPainter::Antialiasing);view.setBackgroundBrush(QPixmap(":/images/cheese.jpg"));

为了能够欧看到场景,我们需要创建一个场景的窗体,QGraphicsView 类 可以提供一个自带滚动条的窗体。我们确保图形的渲染是抗锯齿的。通过背景刷绘制一个背景。

   view.setCacheMode(QGraphicsView::CacheBackground);view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);view.setDragMode(QGraphicsView::ScrollHandDrag);

设置缓存机制。QGraphicsView 可以预渲染像素化的图形。

设定拖拽模式。ScrollHandDrag 该模式下,当鼠标拖拽时会变为手型,同时滚动条会随之变化。

      view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice"));view.resize(400, 300);view.show();QTimer timer;QObject::connect(&timer, &QTimer::timeout, &scene, &QGraphicsScene::advance);timer.start(1000 / 33);return app.exec();}

最后设定窗体的标题,创建一个定时器,设定定时器的超时事件来调用场景的帧的步进。

Qt 视图框架示例 Colliding Mice 的翻译相关推荐

  1. Qt工作笔记-ListWidget拖动(拖拽)到QGraphicsScene【补坑】【Qt视图框架补坑】

    关于以前的这篇博文,进行补坑 https://blog.csdn.net/qq78442761/article/details/80957186 坑的位置在这,采用上面这篇博文的配法,无法得到图元在场 ...

  2. Qt Creator Colliding Mice碰撞老鼠例程解析【1.5W字数长文!详细!】

    工程效果 可以看到,小老鼠碰撞后耳朵会变红.具体完整代码可在示例里面找到. 工程总体就是多了一个mouse的源文件和头文件,即Mouse类相关文件.在Graphics View框架结构主要包含三个类: ...

  3. Qt开发技术:图形视图框架(二)场景QGraphicsScene、QGraphicsItem与QGraphicsView详解

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/117660217 长期持续带来更多项目与技术分享,咨询请 ...

  4. Qt图形视图框架图片图元QGraphicsPixmapItem

    文章可能被更新,最新地址:http://www.fearlazy.com/index.php/post/107.html 看这个标题还真有点拗口,一句话里出现了四个图字.这句话的关键词是图片,前面讲了 ...

  5. Qt 图形视图框架(Qt MVC)

    什么是MVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离 ...

  6. Qt修炼手册6_图形:图形视图框架

    1.前言 主要为了学习可以在GUI上有效显示或管理大量图形对象的API,以及进行显示.扩大.缩小等操作. 2.图形视图框架(Graphics View Framework) 图形视图框架使用BSP树算 ...

  7. Qt 图形视图框架中的事件处理和传播

    目录名字 Qt 图形视图框架中的事件处理和传播 要点: Qt 图形视图框架中的事件处理和传播 图形视图框架在一些动画类的应用程序上经常会用到.该框架中的事件处理与传播机制也是经常会涉及. 程序设计核心 ...

  8. Qt 模型视图框架解读之模型

    Qt 模型视图框架 前后阅读的好几遍,要不是项目中需要处理一些相对比较多的数据,这部分内容估计不会去急着去理解. 首先来了解下什么是模型和视图框架吧: 一般地:MVC 设计模式包括三个元素: 表示数据 ...

  9. 【Qt】2D绘图之图形视图框架(一)

    00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 场景(Scene) 04. 视图(View) 05. 图形项 06. 附录 01. 概述 在前面讲的基本绘图中,我们可以自 ...

最新文章

  1. CentOS7(64位)查看CPU和NVIDIA显卡温度
  2. java验证码局部刷新_JS局部刷新图形验证码
  3. 题解 T28305 【yizimi的旅游景点】
  4. 这条路有多长,有多难 | 专访OnVideo创始人余世兵刘歧
  5. Mac OSX使用VMware Fusion安装windows虚拟机教程
  6. Windows7搭建FTP文件
  7. ckeditor3 配置
  8. [转载]舌尖上的清华 I
  9. java简历中的项目经验怎么写_java软件工程师简历中项目经验怎么写?
  10. SDL游戏开发之七-虚拟摇杆
  11. IGBT工作原理,解析IGBT工作原理及作用
  12. 工商银行java script error windows7_Win8.1装工行网银提示"called runscript when not marked in progress"的解决方法...
  13. 【LeetCode】75. Sort Colors(颜色排序)-C++实现的两种方法及超详细图解
  14. matlab-线性代数 det 各阶主子式、余子式、代数余子式
  15. 设计分享|基于51单片机的数字时钟(汇编)
  16. SpringBoot日记本系统全程直播09:项目一期完结
  17. 服务器地址怎么查 如何远程登录服务器教程
  18. Math类,随机数Random类,System类,BigInteger类,BigDecimal类,Date类,Calendar类
  19. 基于混合模型的语音降噪实践
  20. EchartsY轴刻度自适应

热门文章

  1. 冒泡排序python实现
  2. tensorboard出现OSError: [Errno 22] Invalid argument问题解决
  3. USTC English Club Note20171012(4)
  4. [MATLAB学习笔记] global声明全部变量
  5. mysql和oracle的锁_关于数据库行锁与表锁的认识
  6. adf检验代码 python_第22期:向量自回归(VAR)模型预测——Python实现
  7. python处理rgb_如何在Python中读取给定像素的RGB值?
  8. Spatial Pyramid Pooling(空间金字塔池化)-变尺度CNN训练
  9. C++Primer:函数(参数传递:引用形参)
  10. TeeChart用法(网络收集)默认分类 2010-03-05 21:46:05 阅读788 评论0 字号:大中小 .