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中的鼠标修改成十字
展示的是主要代码,并不是全部代码,如果需要全部代码请联系博主获取
相关文章:
QT图形视图系统 - 使用一个项目来学习QT的图形视图框架 - 终篇
QT图形视图系统 - 终篇 接上一篇,我们需要继续完成以下的效果; 先上个效果图: 修改背景,使之整体适配 上一篇我们绘制了标尺,并且我们修改了放大缩小和对应的背景,整体看来,我们的滚动条会和…...
代码随想录算法训练营第六十天|单调栈part03|● 84.柱状图中最大的矩形
84.柱状图中最大的矩形 Largest Rectangle in Histogram - LeetCode 单调栈这几题没过脑,感觉一团浆糊,要重新看一下 class Solution {public int largestRectangleArea(int[] heights) {Stack<Integer> stack new Stack<>();int[] newHeig…...
TCP的三次握手四次挥手
TCP的三次握手和四次挥手实质就是TCP通信的连接和断开。 三次握手:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。 四次挥手&a…...
xml的学习笔记
学习视频:093-尚硅谷-xml-什么是XML以及它的作用_哔哩哔哩_bilibili 目录 XML简介 XML的作用 XML语法 1.文档声明 2.xml注释 3.元素标签 4.xml属性 5.语法规则 1.所有xml元素都须有关闭标签(也就是闭合) 2.xml 标签对大小写敏感 3.xml必须正确的嵌套 4…...
大数据之Hadoop(一)
目录 一、准备三台服务器 二、虚拟机间配置免密登录 三、安装JDK 四、关闭防火墙 五、关闭安全模块SELinux 六、修改时区和自动时间同步 一、准备三台服务器 我们先准备三台服务器,可以通过虚拟机的方式创建,也可以选择云服务器。 关于如何创建虚…...
Ubuntu安装git
使用 apt-get install git 安装git 报错: 这个错误信息通常表示您的系统上没有可用的 git 软件包。这可能是因为您的软件源列表中没有包含 git 软件包所在的软件源,或者您的软件源列表已经过期。 解决: 如果您使用的是 Ubuntu 或类似…...
[迁移学习]领域泛化
一、概念 相较于领域适应,领域泛化(Domain generalization)最显著的区别在于训练过程中不能访问测试集。 领域泛化的损失函数一般可以描述为以下形式: 该式分为三项:第一项表示各训练集权重的线性组合,其中π为使该项最小的系数&a…...
240. 搜索二维矩阵 II
240. 搜索二维矩阵 II 原题链接:完成情况:解题思路:参考代码: 原题链接: 240. 搜索二维矩阵 II https://leetcode.cn/problems/search-a-2d-matrix-ii/description/ 完成情况: 解题思路: 从…...
【Linux:线程池】
文章目录 1 线程池概念2 第一个版本的线程池3 第二个版本的线程池4 第三个版本的线程池5 STL中的容器以及智能指针的线程安全问题6 其他常见的各种锁7 读者写者问题(了解) 1 线程池概念 一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而…...
跨境多商户中日韩英多语言商城搭建(PC+小程序+H5),搭建方案
随着全球化的推进,跨境电商正变得越来越普遍。在本文中,我们将介绍跨境电商系统开发中多语言商城独立站的部署搭建方案。 准备工作 在开始部署搭建之前,需要准备以下环境: 服务器,确保服务器具备足够的性能和稳定性。 …...
使用标准库版本编写LED闪烁
1、在STM32CubeMX中创建一个新的工程,选择STM32F103VCT6作为目标设备,并配置好所需的引脚和时钟设置。将需要用于LED连接的GPIO引脚设置为输出模式。 2、在生成代码后,打开工程目录,在Src文件夹中创建一个新的main.c文件。 3、在…...
【CDC】跨时钟域处理方法总结一
文章目录 一、概述1.异步时序2.亚稳态与建立保持时间 二、跨时钟域处理1.控制信号的跨时钟域处理(单bit数据)a.慢时钟域到快时钟域b.快时钟域到慢时钟域握手“扩宽”快时钟域脉冲时钟停止法窄脉冲捕捉电路 2.数据信号的跨时钟域处理(多bit数据…...
【Linux】创建分区后没有识别到分区盘?
如果在使用fdisk创建分区后明明输入p可以看到新建分区,但是lsblk查看的时候没有该分区,系统可能没有识别,你需要手动重新加载一下分区。 partprobe命令 partprobe命令用于重读分区表,将磁盘分区表变化信息通知内核,请求…...
W6100-EVB-PICO做DNS Client进行域名解析(四)
前言 在上一章节中我们用W6100-EVB-PICO通过dhcp获取ip地址(网关,子网掩码,dns服务器)等信息,给我们的开发板配置网络信息,成功的接入网络中,那么本章将教大家如何让我们的开发板进行DNS域名解…...
{Fixed} Android TV国内开机不会自动连接WIFI / 连接国内网络不会更新时间
引用: 悟空百科 使用usb adb、网络adb、串口敲以下命令修改安卓全局数据库 1、写入新的ntp服务器地址 adb shell settings put global ntp_server ntp.ntsc.ac.cn2、打开网络验 //如果你是Android R 以上的电视盒子 adb shell settings put global captive_portal_mode 1/…...
【ASP.NET MVC】数据到客户端(7)
前文ViewBag数据在服务端动态生成页面,也可以传到客户端浏览器供JS使用。 一、数据从控制器到客户端 前文介绍,动态生成页面时,控制器的数据 并没有传递到 客户端,而是给自己来用,生成View 再利用http传递到客户端浏…...
InnoDB有哪些特性
事务支持:InnoDB支持ACID(原子性、一致性、隔离性和持久性)事务,可以保证数据的完整性和一致性。它使用多版本并发控制(MVCC)来实现事务的隔离性,支持读已提交和可重复读两种隔离级别。 行级锁…...
【linux--->数据链路层协议】
文章目录 [TOC](文章目录) 一、数据链路层协议概念二、以太网帧格式1.字段分析 三、局域网通信原理四、ARP协议1.结构2.作用3.ARP通信过程4.ARP协议相关命令 五、局域网内中间人原理六、DNS系统(域名系统)1.域名概念2.DNS系统组成3.DNS协议3.浏览器输入域名后的通信过程4.dig工…...
如何在pytest接口自动化框架中扩展JSON数据解析功能?
开篇 上期内容简单说到了。params类类型参数的解析方法。相较于简单。本期内容就json格式的数据解析,来进行阐述。 在MeterSphere中,有两种方式可以进行json格式的数据维护。一种是使用他们自带的JsonSchema来填写key-value表单。另一种就是手写json。…...
哪些年,我们编程四处找的环境依赖
基于Maven,快速构建SSM项目 <properties><!-- 将spring和有关的升级版本,设置为5.0.5--><spring.version>5.0.5.RELEASE</spring.version><!-- 将mybatis和有关的升级版本,设置为3.1.1--><my…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
命令行关闭Windows防火墙
命令行关闭Windows防火墙 引言一、防火墙:被低估的"智能安检员"二、优先尝试!90%问题无需关闭防火墙方案1:程序白名单(解决软件误拦截)方案2:开放特定端口(解决网游/开发端口不通)三、命令行极速关闭方案方法一:PowerShell(推荐Win10/11)方法二:CMD命令…...
Mac flutter环境搭建
一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...
