QT图形视图系统 - 使用一个项目来学习QT的图形视图框架 - 终篇

QT图形视图系统 - 终篇

接上一篇,我们需要继续完成以下的效果;

先上个效果图:

在这里插入图片描述

修改背景,使之整体适配

上一篇我们绘制了标尺,并且我们修改了放大缩小和对应的背景,整体看来,我们的滚动条会和背景不搭配,因此我们需要修改我们的背景,这里使用qss修改;并且我们把之前的背景也写到这个里面。

style1.qss

QGraphicsView
{background: #000000;
}QScrollBar:horizontal {border: none;background: #000000;height: 15px;
}
QScrollBar::handle:horizontal {background: white;min-width: 20px;
}
QScrollBar::add-line:horizontal {border: none;background: #000000;width: 0px;
}QScrollBar::sub-line:horizontal {border: none;background: #000000;width: 0px;subcontrol-position: left;subcontrol-origin: margin;
}
/*QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal {*/
/*    border: 2px solid grey;*/
/*    width: 3px;*/
/*    height: 3px;*/
/*    background: white;*/
/*}*/QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {background: none;
}QScrollBar:vertical {border: none;background: #000000;width: 15px;border-bottom: 1px solid red;
}
QScrollBar::handle:vertical {background: white;min-height: 20px;
}
QScrollBar::add-line:vertical {border: none;background: #000000;height: 0px;subcontrol-position: bottom;subcontrol-origin: margin;
}QScrollBar::sub-line:vertical {border: none;background: #000000;height: 0px;subcontrol-position: top;subcontrol-origin: margin;
}
QScrollBar:up-arrow:vertical, QScrollBar::down-arrow:vertical {border: 2px solid grey;width: 3px;height: 3px;background: white;
}QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {background: none;
}

然后我们加载这个qss即可, 将之前设置qss的地方修改成读取这个文件

QFile file(":/resources/qss/style1.qss");
file.open(QIODevice::ReadOnly);
// 设置软件背景色
setStyleSheet(QString(file.readAll()));
file.close();

绘制对应刻度的线条

QGraphicsView有两个函数,一个是绘制背景色,一个是绘制前景色。我们的样条实际上绘制的是背景色,因此我们需要重写这两个函数;

void drawForeground(QPainter* painter, const QRectF& rect) override;
void drawBackground(QPainter* painter, const QRectF& rect) override;

去掉之前再scene中添加的文字,我们接下来开始绘制

背景没有什么好说的,直接绘制成黑色的就可以

void GraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
{painter->fillRect(rect, Qt::black);// QGraphicsView::drawBackground(painter, rect);
}

接下来我们通过前景色来绘制刻度线

constexpr int32_t uScale = 100000;
constexpr double dScale = 1.0 / uScale;
static std::unordered_map<int, int> gridLinesX, gridLinesY;void GraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
{// fixme 这个地方需要修改成按照单位转换的double scale =  pow(10.0, ceil(log10(8.0 / h_ruler_->zoom())));double lineWidth {0};gridLinesX.clear(), gridLinesY.clear();const QColor color[4] {{255, 0, 0, 127}, // 0处使用红色绘制QColor(100, 100, 100, 50),  // Grid1QColor(100, 100, 100, 150), // Grid5QColor(100, 100, 100, 255), // Grid10};double y, x;draw(scale * 0.1, rect, x, y);draw(scale * 0.5, rect, x, y);draw(scale * 1.0, rect, x, y);gridLinesX[0] = 0;gridLinesY[0] = 0;static QVector<QLineF> lines[4];for (auto&& vec : lines)vec.clear();double tmp {};for (auto [x, colorIndex] : gridLinesX) {tmp = x * dScale;lines[colorIndex].push_back(QLineF(tmp, rect.top(), tmp, rect.bottom()));}for (auto [y, colorIndex] : gridLinesY) {tmp = y * dScale;lines[colorIndex].push_back(QLineF(rect.left(), tmp, rect.right(), tmp));}painter->save();painter->setRenderHint(QPainter::Antialiasing, false);int colorIndex {};for (auto&& vec : lines) {painter->setPen({color[colorIndex++], lineWidth});painter->drawLines(vec.data(), vec.size());}auto width { rect.width() };auto height { rect.height() };painter->setPen({Qt::yellow, 0.0});painter->drawLine(QLineF {point_.x() - width, point_.y(), point_.x() + width, point_.y()});painter->drawLine(QLineF {point_.x(), point_.y() - height, point_.x(), point_.y() + height});painter->restore();
}void GraphicsView::draw(double sc, const QRectF& rect, double &x, double &y)
{if (sc >= 1.0) {int top = floor(rect.top());int left = floor(rect.left());y = top - top % int(sc);x = left - left % int(sc);} else {const double k = 1.0 / sc;int top = floor(rect.top()) * k;int left = floor(rect.left()) * k;y = (top - top % int(k)) / k;x = (left - left % int(k)) / k;}for (const auto end_ = rect.bottom(); y < end_; y += sc)++gridLinesY[ceil(y * uScale)];for (const auto end_ = rect.right(); x < end_; x += sc)++gridLinesX[ceil(x * uScale)];
}

这样我们便有了网格线

下面的函数是对ruler和鼠标移动时候的操作

void GraphicsView::updateRuler()
{updateSceneRect(QRectF()); //QPoint p = mapFromScene(QPointF());v_ruler_->setOrigin(p.y());h_ruler_->setOrigin(p.x());v_ruler_->setRulerZoom(qAbs(transform().m22() * 0.1));h_ruler_->setRulerZoom(qAbs(transform().m11() * 0.1));update();
}void GraphicsView::mouseMoveEvent(QMouseEvent *event)
{QGraphicsView::mouseMoveEvent(event);v_ruler_->setCursorPos(event->pos());h_ruler_->setCursorPos(event->pos());point_ = mapToScene(event->pos());emit sig_mouseMove(event->pos());update();
}

我们之前对鼠标样式进行了修改,这个里面也不要忘记将View中的鼠标修改成十字
展示的是主要代码,并不是全部代码,如果需要全部代码请联系博主获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/28222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fastadmin自定义键值组件Fieldlist

需求场景&#xff1a; 后台设置前端的固定话费充值金额。编辑时要求能够增删改&#xff0c;给到前端的数据&#xff0c;是要根据金额正序排列&#xff0c;用fastadmin的键值组件(Fieldlist)&#xff0c;使用Art-Template模板语法自定义模板。 最终效果如下图所示&#xff1a; …

SpringBoot+MyBatis多数据源配置

1.先在配置文件application.yml中配置好数据源 spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedb1:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rootjdbc-url: jdbc:mysql://192.168.110.128:3306/CampusHelp?useUnicodeyes&…

vscode extension 怎么区分dev prod

开发模式注入环境变量 使用vsode 提供的api

WebRTC | 音视频直播客户端框架

端到端通信互动技术可分解为以下几个技术难点&#xff1a;客户端技术、服务器技术、全球设备网络适配技术和通信互动质量监控与展示技术。 一、音视频直播 音视频直播可分成两条技术路线&#xff1a;一条是以音视频会议为代表的实时互动直播&#xff1b;另一条是以娱乐直播为代…

在工作中使用ChatGPT需要担心泄密问题吗?

​OpenAI的ChatGPT可以通过自动简化繁琐的任务&#xff0c;针对挑战性问题的提供创造性的解决方案来提高员工的生产力。但随着这项技术被整合到人力资源平台和其他工作场所中&#xff0c;它给各个企业带来了巨大的挑战。苹果、Spotify、Verizon和三星等大公司已禁止或限制员工在…

Java分布式微服务1——注册中心(Eureka/Nacos)

文章目录 基础知识注册中心Eureka注册中心与Ribbon负载均衡1、Eureka注册中心2、Eureka的搭建3、Eureka服务注册4、复制服务实例5、拉取服务6、Ribbon负载均衡的流程及Eureka规则调整&#xff1a;7、Ribbon负载均衡饥饿加载 Nacos注册中心1、服务端Nacos安装与启动2、客户端Nac…

【如何构建自己的基于Arduino的Scara 机器人】

【如何构建自己的基于Arduino的Scara 机器人】 1. 概述2. Scara机器人3D模型3. 3D打印机器人零件4. 组装机器人5. SCARA机器人电路图6. 完成装配7. SCARA机器人的工作原理8. 对 SCARA 机器人进行编程 – Arduino 和处理代码9. 总结在本教程中,我们将学习如何构建基于 Arduino …

明年,HarmonyOS不再兼容Android应用!

2023年华为开发者大会&#xff0c;不知道各位老铁们是否观看了&#xff0c;一个震撼的消息就是&#xff0c;首次公开了HarmonyOS NEXT的概念&#xff0c;简而言之就是&#xff0c;这是一款专为开发者打造的预览版操作系统&#xff0c;旨在提供"纯正鸿蒙操作系统"的体…

【前端实习生备战秋招】—HTML 和 CSS面试题总结(三)

【前端实习生备战秋招】—HTML 和 CSS面试题总结&#xff08;三&#xff09; 1.行内元素有哪些&#xff1f;块级元素有哪些&#xff1f; 空(void)元素有那些&#xff1f; CSS 规范规定&#xff0c;每个元素都有 display 属性&#xff0c;确定该元素的类型&#xff0c;每个元素…

体验自制免费开源闯关学SQL

文章目录 前言mac安装nodejs启动体验 前言 sql是常用必不可少的一种语言&#xff0c;我们都或有各种各样的学习经历&#xff0c;最近看鱼皮大佬开源了一款自制的闯关学SQL项目&#xff0c;该项目是纯前端语言&#xff0c;不需要太多依赖以及前置知识&#xff0c;直接下载就可以…

pg实现月累计

获取每月累计数据&#xff1a; ​​​ SELECT a.month, SUM(b.total) AS total FROM ( SELECT month, SUM(sum) AS total FROM ( SELECT to_char(date("Joinin"),YYYY-MM) AS month , COUNT(*) AS sum FROM "APP_HR_Staff_Basic_Info" GROUP BY month ) …

Clickhouse 存储引擎

一、常用存储引擎分类 1.1 ReplacingMergeTree 这个引擎是在 MergeTree 的基础上&#xff0c;添加了”处理重复数据”的功能&#xff0c;该引擎和MergeTree的不同之处在于它会删除具有相同主键的重复项。 特点: 1使用ORDERBY排序键作为判断重复的唯一键 2.数据的去重只会在合并…

Android 13 Launcher——屏蔽长按非icon区域出现弹窗

目录 一.背景 二.屏蔽此功能 一.背景 长按Launcher非icon区域也是会有弹窗的&#xff0c;会显示小组件等信息&#xff0c;定制开发要求长按非icon区域不要弹窗&#xff0c;我们来实现此功能&#xff0c;先看下未修改前的长按非icon区域的效果 如上图可以看出长按功能显示出壁…

电力系统电流三段式保护MATLAB仿真模型

整体模型如下&#xff1a; Matlab/Simulink搭建的电力系统电流保护模型采用辐射型单电源供电的运行方式 Ⅰ段保护的搭建 Ⅰ段保护为瞬时速断保护&#xff0c;根据Ⅰ段整定原则确定整定值。线路发生短路故障时&#xff0c;短路电流急剧增大&#xff1b;超过设置的整定值时&…

大数据-玩转数据-Flink-Transform

一、Transform 转换算子可以把一个或多个DataStream转成一个新的DataStream.程序可以把多个复杂的转换组合成复杂的数据流拓扑. 二、基本转换算子 2.1、map&#xff08;映射&#xff09; 将数据流中的数据进行转换, 形成新的数据流&#xff0c;消费一个元素并产出一个元素…

Unity 3D中使用tilemap创建关卡地图,瓦片间隙有漏缝

我们使用一张图片来作为Sprite图集&#xff0c;创建地形图&#xff1a; 运行后&#xff0c;会发现&#xff0c;瓦片之间似乎总是有间距。 检查了图片发现&#xff0c;并不是图片边界存在间隙。 最后发现问题是出在图片资源中的线性过滤属性值&#xff1a; 在设计界面就能够看…

ETHERCAT转CANOPEN协议网关canopen分类

1.产品功能 JM-ECT-COP是自主研发的一款 ETHERCAT 从站功能的通讯网关。该产品主要功能是将 ETHERCAT 网络和 CANOPEN 网络连接起来。 本网关连接到 ETHERCAT 总线中做为从站使用&#xff0c;连接到 CANOPEN 总线中做为主站使用。 3.技术参数 ETHERCAT 技术参数 网关做为 E…

【设计模式——学习笔记】23种设计模式——中介者模式Observer(原理讲解+应用场景介绍+案例介绍+Java代码实现)

文章目录 案例引入案例一普通实现中介者模式 案例二 介绍基础介绍登场角色尚硅谷 《图解设计模式》 案例实现案例一&#xff1a;智能家庭类图实现 案例二&#xff1a;登录页面逻辑实现说明类图实现 总结文章说明 案例引入 案例一 普通实现 在租房过程中&#xff0c;客户可能…

PHP最简单自定义自己的框架定义常量自动生成目录(三)

1、框架入口增加模块定义&#xff0c;实现多模块功能 index.php 定义模块 <?php //定义当前请求模块 define("MODULE",index); require "./core/KJ.php"; 创建后台模块admin.php <?php define("MODULE",admin); require "./cor…

每日一题——最小花费爬楼梯

题目 给定一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第i 个台阶向上爬需要支付的费用&#xff0c;下标从0开始。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶部的…