QPainter绘图工具的完善

2023-11-05

上一篇:QPainter实现简单的绘图程序(绘图工具)


前言

gitee工程地址: PaintTool_03

学习了简单的绘图工具后,程序略显基础与简单。接下来就开始改善上一篇文章的程序,增添撤回和橡皮擦功能。
为了偷懒,我直接上传工程,然后解释一些程序的关键点,因为程序稍大了后即使一步一步分析思路,还不如自己找关键程序段分析来的快。


在这里插入图片描述

撤回功能的理解

上篇的程序可以看到,画基本图形与画笔都可以用path来存储,那么我们只需要引入QStack<QPainterPath>栈来存储每一次的绘图,这样便可以通过出栈的方式来撤销一步绘图

//变量声明
QPainterPath path;          //临时绘画路径
QStack<QPainterPath> paths; //绘画路径栈

拆分的理解

  1. 普通图的撤销(圆形、矩形、直线)。
  2. 画笔工具的撤销。
  3. 橡皮擦工具。

一、重绘函数的写法

/*
*image相当于所有绘图的储存容器,而path是当前正在绘制的图形
*可以理解为:对于基本图形,是在松开鼠标后才将最终的path存到image中
*对于画笔和擦皮来说,是直接画在image里,因为鼠标路径就是最终绘图路径,不需要path来缓存(希望这里能仔细理解)
*/
if(event->type()==QEvent::Paint){
   painter.begin(this);
    painter.drawImage(0,0,image);	//绘制画好的图片

    if(!path.isEmpty()){	//path代表当前正在画的路径,不为空说明正在画图,那么先把这个路径绘制出来。
        if(num==5)//如果是橡皮,则设置painter为擦除模式,将绘画处擦出成完全透明的区域
            painter.setCompositionMode(QPainter::CompositionMode_Clear);
        else	//否则,即不是橡皮工具,则设置基础的画笔样式
            Widget::setPenStyle();
        painter.drawPath(path);
    }
    painter.end();
}

二、绘制判断

if(event->type()==QEvent::MouseButtonPress){
   first = last = e->pos();
    if(num==4){
        path = QPainterPath(first);
        paths.push(path);
    }
    this->update();
}
......
......
//下面判断存在于鼠标移动事件中
//1矩形 2圆形 3直线 4画笔 5橡皮
switch (num) {	
case 1:
    path.clear();//每次移动都重新绘制路径
    //normalized()方法可以重新整理矩形,让矩形的左上与右下两个点处于正确的相对位置
    path.addRect(QRect(first,last).normalized());
    break;
case 2:
    path.clear();
    path.addEllipse(QRect(first,last).normalized());
    break;
case 3:
    path.clear();
    path = QPainterPath(first);	//设置绘画路径的落笔点,默认为0,0
    path.lineTo(last);	//当前笔所在点画到last点处,那么现在笔就会在last点的位置,这也是为什么上面要将落笔点设置为first
    break;
case 4:		//画笔工具
    path.lineTo(last);
    pointsNum++;	//计数当前点的个数
    if(pointsNum>255){	//超过255
        Widget::drawPathtoImage();	//那么视作path存满了,直接画在image里(存多了会出现第一篇的情况,花圈出现卡顿呈多边形的现象)
        paths.last().addPath(path); //这里看鼠标按下事件里面的特判,如果是画笔工具,那么提前添加了一个空路径,
        						    //只要这次绘画没断笔,是一条线,则加入到属于当前路径的变量中,这样撤回时便不是只撤回255个点的路径,而是一整条线
        path.clear();			    //清空临时绘图路径
        path = QPainterPath(last); //并将笔落在最后一次落笔的位置,这样才可以将线连起来
        pointsNum=1;			   //重新设置path路径中点的个数
    }
    break;
case 5:	//橡皮擦
    painter.setCompositionMode(QPainter::CompositionMode_Clear);//设置成清除模式
    painter.setBrush(QColor(0,0,0,0));	//设置成画刷填充
    painter.drawEllipse(last,10,10);	//直接擦除image中以落笔处为中心,半径为10的圆
    break;
}
......
......

三、橡皮擦

......
......
switch (num) {	
......
......
case 5:		//橡皮擦
    painter.setCompositionMode(QPainter::CompositionMode_Clear);//设置成清除模式
    painter.setBrush(QColor(0,0,0,0));	//设置成画刷填充
    painter.drawEllipse(last,10,10);	//直接擦除image中以落笔处为中心,半径为10的圆
    break;
}
......
......

该程序仍是初学者的练习程序,改进需要自己动脑,这里只是一个思路,想要直接找成品完成项的同志,就不要在这里浪费时间了,本篇文章只是练习为目的,也提供了一个实现功能的思路,而,已。


感谢各位的观看

下一篇: QPainterPath路径类的使用(图像移动)


tips: 今日蓝桥杯成绩出炉,在下作为软件工程的人,居然拿了电子类嵌入式的省一,实属荣幸。

即使我心中的只有那充满铜臭味的金钱奖励



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QPainter绘图工具的完善 的相关文章

  • QTcpSocket 有时不发送数据

    我有两个 QT 应用程序 一个应用程序可以被认为保存了大数据 它每秒向第二个应用程序发送大约 10 KB 的数据块 之前我尝试使用QUdpSocket来传输数据 但由于MTU限制在2 5K左右 并且需要自己分割和重新组合数据 所以我改用QT
  • 如何在带有预编译头的项目中使用google protobuf

    我有一个包含多个项目的解决方案 我的项目 但不是全部 使用预编译头 我决定使用 protobuf 但遇到了一个问题 在 protoc exe 从 proto 生成 pb h 后 我尝试包含标头并收到错误 预编译标头未包含在 pb h 中 我
  • QGraphicsScene::clear 不会改变 sceneRect

    我有一个 QGraphicsScene 场景 和 QGraphicsView graphicsView 我有一个画图的方法 当我需要重绘所有图形时 我调用这个方法 一切都好 但我意识到 scene gt clear 不会改变 sceneRe
  • 向 Qt 样式表添加特异性时丢失样式

    这是我的代码 const QString STYLE SHEET background color rgba x x x y border 1px solid gray border radius 0px border top 1px so
  • 如何将图像显示为缩略图

    我有一个QTreeView显示硬盘驱动器和目录 我也有一个QListView显示图像文件如下 但我想将图像显示为缩略图 如下所示 My code mainWidget mainWidget QWidget parent QWidget pa
  • 退出 Qt 程序的正确方法?

    我应该如何退出 Qt 程序 例如在加载数据文件时 发现文件损坏 并且用户需要退出该应用程序或重新启动数据文件 我是不是该 call exit EXIT FAILURE call QApplication quit call QCoreApp
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959
  • 如何使QTableView类的restoreState()和saveState()正常工作?

    首先 我想说 我的问题已经在这里讨论过 并且这里是 https stackoverflow com questions 1163030 qt qtableview and horizontalheader restorestate 但答案并
  • 即使在可访问性中勾选应用程序,AXIsProcessTrustedWithOptions 也不会返回 true

    As this question https stackoverflow com questions 17693408 enable access for assistive devices programmatically on 10 9
  • Qt:测量事件处理时间

    我想测量我的应用程序中的哪些事件在主线程中需要很长时间才能执行 阻塞 GUI 或者至少是否有任何事件花费的时间超过 比如说 10 毫秒 显然 我对需要很长时间的任务使用线程和并发 但有时很难在其他线程中放入的内容和可以保留在 GUI 中的内
  • 在 MacOS 终端上运行 ffmpeg [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我对 MacOS 相当陌生 我发现使用终端来获取信息并不容易ffmpeg和我在 Window 上一样正常运行 我有 ffmpeg 二进制文件ffmpe
  • 从 Qt4 中的文本文件中逐字读取

    我想在 Qt4 中逐字读取一个文本文件 说实话我对它很陌生 我想在另一个文件中每行一个字写入 我可以在 C 中做到这一点 没有任何问题 但是当我尝试在 Qt4 中使用 ifstream 和 ofstream 时 我遇到了错误 这是我的 Qt
  • 如何在 QtQuick 2 中对 QML TableView 进行排序?

    我想使用 Qt 5 1 实现具有自定义角色的可排序 TableView 但我不知道当用户单击标题时该怎么做才能对其进行排序 在我的 Qt pro 文件中 我添加了 android ios blackberry qtHaveModule wi
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • Qt 5.3 无法使 QCompass (QSensor) 在 Windows 8.1 上工作

    我无法让传感器在我的 Asus Transformer T100 上工作 磁力计和指南针无法启动 并且我从加速度计获得假值 始终 x 0 y 9 8 z 0 即使使用我的笔记本电脑 我总是得到相同的结果 第一段文字编辑 Initialisa
  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • Qt 安装程序框架 - 如何在卸载时仅删除某些文件和文件夹

    我使用 Qt 安装程序框架 如何确保在卸载时仅删除某些文件或文件夹 而不是像当前那样删除安装文件夹中的所有文件 先感谢您 您可以覆盖默认行为component createOperations对于卸载程序 然后使用手动指定每个卸载路径com
  • 如何消除 QTableWidget 中的空白?

    How do I get rid of the whitespace in my application 我想摆脱 QTableWidget 中的空白 蓝色箭头 我该怎么做 这是我的应用程序的代码 gridLayout QGridLayou
  • 如何访问Loader的sourceComponent中的QML对象?

    我可能需要读取或写入的一些属性Loader s sourceComponent来自一些外部函数 访问该房产的方式是什么x里面的对象的Loader s sourceComponent import QtQuick 2 0 Item width
  • 在 Qthread 中运行函数 - 应用程序将挂起

    我在 QT 内部线程方面遇到一些问题 include

随机推荐

  • windows cmd下用命令创建和删除文件、文件夹

    新建文件夹和文件 cd 返回上一级 md test 新建test文件夹 md d test my d盘下新建文件夹 cd test 进入test文件夹 cd gt cc txt 新建cc txt文件 dir 列出文件夹下所有文件及文件夹 删
  • Scratch2舞台各个部分及积木的介绍

    软件界面分为舞台区 背景角色区和工作区 其中 工作区包含脚本 造型和声音是哪个选项卡功能 积木部分需要着重介绍 这也是接下来 小朋友要格外关注的部分 积木区主要指 脚本选项卡下的内容 包括 1 运动类积木 2 外观类积木 3 声音类积木 4
  • XStream配置XML节点既有属性又有内容

    例如XML节点为这样的 如何通过XStream来映射JavaBean呢
  • 湖北文理学院工程能力实训开班!

    为深化校企合作 产教融合助力新工科建设 提升学生工程实践能力 电巢工程能力实训班按照不同岗位类别 匹配对应的企业岗位任职能力要求对学生开展分级培养 以产业需求为导向 培养创新型 应用型人才 7月3日中午12时 深圳电巢联合湖北文理学院物理与
  • 【pytorch入门】Anaconda安装+pytorch安装+pycharm安装教程

    前言 Anaconda是一个开源的Python发行版本 其包含了conda Python等180多个科学包及其依赖项 其中包括Conda Python以及一大堆安装好的工具包 比如 numpy pandas等 安上之后 基本就包括后面学习所
  • pm2入坑教程

    PM2入坑教程 一 使用场景 二 使用命令 2 1 安装pm2的命令 2 2 创建启动 2 3 查看命令 2 4 删除命令 2 5 停止命令 2 6 结束进程 一 使用场景 1 普通启动方式 node index js 关闭终端就结束进程
  • Windows下批处理管理Nginx应用程序

    每次更新完配置 通过命令行或者任务管理器来操作Nginx重启 操作起来 显得有点麻烦 下面脚本就是解决这个问题的 cls echo off set NGINX PATH d0 set NGINX DIR cd color 0a title
  • 微软:从“开源是毒瘤”到“我爱Linux”的20年

    整理 彭慧中 责编 屠敏 出品 CSDN ID CSDNnews 英国前首相帕麦斯顿曾说过 没有永远的朋友 也没有永远的敌人 只有永远的利益 这句话用来形容微软对于开源的态度正合适 在21世纪初 曾视开源为 毒瘤 并一度想将其毁灭的微软 现
  • 优化算法选择:SGD、SGDM、NAG、Adam、AdaGrad、RMSProp、Nadam

    目录 优化算法通用框架 SGD 系列 固定学习率的优化算法 SGD SGD with Momentum SGD M SGD with Nesterov Acceleration NAG 自适应学习率的优化算法 AdaGrad AdaDelt
  • 18. TypeScript 扩展全局变量类型

    TypeScript 扩展全局变量类型 1 扩展局部变量 可以直接使用接口对已有类型进行扩展 interface String double string String prototype double function return th
  • css学习——sass(6)

    第一步 全局安装 sass 在命令行工具 npm install g sass 查看版本 sass version 第二步 手动将sass 编译为css 1 创建一个test scss 2 在命令行终端 输入sass test scss t
  • AQS相关工实现类的使用及其原理

    文章目录 1 AQS 1 1 概述 1 2 自定义不可重入锁 2 ReentrantLock 2 1 非公平锁 2 1 1 加锁解锁流程 2 1 1 1 加锁失败 2 1 1 2 解锁竞争 2 2 可重入原理 2 3 可打断原理 2 3 1
  • 虚拟乒乓球连接不上服务器,虚拟乒乓球正版

    虚拟乒乓球正版 游戏画面场景设定的比较小清新 不过其中的内容设定是超级的精彩 极其逼真的玩家操作定能带给各位最为真实的游戏体验 这个过程你需要不断锻炼自己的水平 更得要击败尽可能多的对手 玩法难度可供选择 喜欢的玩家快快点击下载试玩吧 游戏
  • 解决jdbc连接本地mysql数据库时报错Caused by: java.net.UnknownHostException: mysql

    今天在写代码的时候遇到的问题 解决问题后记录下 The last packet sent successfully to the server was 0 milliseconds ago The driver has not receiv
  • Mali GPU OpenGL ES 应用性能优化--测试+定位+优化流程

    1 使用DS 5 Streamline定位瓶颈 DS 5 Streamline要求GPU驱动启用性能测试 在Mali GPU驱动中激活性能测试对性能影响微不足道 1 1 DS 5 Streamline简介 可使用DS 5 Streamlin
  • 解决VS中scanf()函数报错问题的四种方案(详细)

    scanf函数在VS中报错的主要原因是 scanf被认为不安全而被编译器默认设置为禁用 那么如何解决这个问题呢 法一 仅将函数scanf替换为scanf s即可 其他语法不变 但scanf s函数并不是C语言函数库里的标准函数 而是VS编译
  • Android中显示网页的多种方式

    在android中显示页面主要有两种方式 一种是在Activity里面直接显示网页 另一种是调用浏览器显示网页 方式不同 使用的方法也不同 下面我们分别讲解 一 在Activity里面直接显示网页 1 在Manifest xml文件里添加I
  • Ubuntu 安装anaconda后,自动进入base虚拟环境解决

    Ubuntu关闭anaconda自动进入base虚拟环境 在Ubuntu上安装完anaconda后 发现每次打开终端后都会自动进入到base的虚拟环境中去 虽然在这些环境下使用问题不大 但一些软件的安装在虚拟环境下有影响 每次使用conda
  • juc并发包整理

    目录 JUC提供了java并发编程需要的类 主要分几个大模块 1 原子类操作 2 锁 3 阻塞队列 4 并发集合 5 同步器 6 线程池 7组合式异步编程 JUC的作者Doug Lea神一样的人物 其中以上很多类的实现底层实现都是基于AQS
  • QPainter绘图工具的完善

    上一篇 QPainter实现简单的绘图程序 绘图工具 文章目录 前言 撤回功能的理解 拆分的理解 一 重绘函数的写法 二 绘制判断 三 橡皮擦 感谢各位的观看 前言 gitee工程地址 PaintTool 03 学习了简单的绘图工具后 程序