当前位置: 首页 > news >正文

Qt基于paintEvent自定义CharView

Qt基于paintEvent自定义CharView

鼠标拖动,缩放,区域缩放, 针对x轴,直接上代码
请添加图片描述

charview.h

#ifndef CHARVIEW_H
#define CHARVIEW_H#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QPointF>class ScaleNode
{
public:QPointF pointScaleOne;QPointF pointScaleTwo;QPointF pointScaleText;double scaleValue;bool bShowScaleText;ScaleNode* nextNode;ScaleNode(){bShowScaleText = false;nextNode = nullptr;}
};class CharView: public QWidget
{
public:CharView(QWidget *parent = nullptr);~CharView();virtual void paintAxisX(QPainter &painter);virtual void paintAxisY(QPainter &painter);virtual void paintCursor(QPainter &painter);virtual void paintData(QPainter &painter);virtual void paintMouseRightMove(QPainter &painter);void UpdeScaleNode();void InitScaleNode();void MouseLeftMoveUpdateStartEndValue();//鼠标左键拖动更新void MouseRightMoveUpdateStartEndValue();//鼠标右键选择更新void MouseWheelUpdateStartEndValue(int flag);//鼠标缩放更新private:void DeleteNode(ScaleNode* node);
protected:virtual void paintEvent(QPaintEvent* event) override;virtual void resizeEvent(QResizeEvent* event) override;virtual void mouseMoveEvent(QMouseEvent* event) override;virtual void mousePressEvent(QMouseEvent* event) override;//鼠标左键按住拖动移动, 右键区域放大virtual void mouseReleaseEvent(QMouseEvent* event) override;virtual void wheelEvent(QWheelEvent* event) override;//滚动鼠标滑轮放大缩小virtual void mouseDoubleClickEvent(QMouseEvent* event) override;//双击恢复默认public:int leftBorder;int topBorder;int rightBorder;int bottomBorder;double scaleValue;int scaleLength;//刻度线高度int scaleTextScaleLength;//带text的刻度线高度int scaleTextHeight;//刻度text高度int scaleTextWidth;//刻度text宽度int scaleTextBorder;//刻度text边距int scaleCnt;//刻度数量double scaleWidth;//刻度宽度int scaleCntShowText;//每多少个刻度显示刻度textdouble startScaleValueInit;//默认刻度开始值double endScaleValueInit;//默认刻度结束值double startScaleValue;//当前刻度开始值double endScaleValue;//当前刻度结束值double everyWidthValue;//每个宽度的值ScaleNode* scaleNodeBegin;//第一个刻度QPointF currentPointF;//当前鼠标位置bool bShowCursor;//是否实现游标bool bPressLeft;//是否鼠标左键按下bool bPressRight;//是否鼠标右键按下QPointF pressPointF;//鼠标左键按下时坐标bool bPressRightMove;//鼠标是否按下移动};#endif // CHARVIEW_H

CharView.cpp

#include "charview.h"#include <QDebug>
CharView::CharView(QWidget *parent):QWidget(parent)
{setMouseTracking(true);setStyleSheet("background-color:rgb(255,255,255);");InitScaleNode();
}CharView::~CharView()
{DeleteNode(scaleNodeBegin);
}void CharView::DeleteNode(ScaleNode *node)
{if(node->nextNode)DeleteNode(node->nextNode);delete node;node = nullptr;
}void CharView::UpdeScaleNode()
{scaleValue = ((double)(endScaleValue - startScaleValue))/scaleCnt;scaleWidth = ((double)(width() - leftBorder - rightBorder))/scaleCnt;everyWidthValue = ((double)(endScaleValue - startScaleValue))/(width() - leftBorder - rightBorder);ScaleNode* node = scaleNodeBegin;int var=0;while(node){node->pointScaleOne = QPointF(leftBorder + var*scaleWidth, height() - bottomBorder);node->pointScaleTwo = QPointF(leftBorder + var*scaleWidth, height() - bottomBorder - scaleLength);node->pointScaleText = QPointF(leftBorder + var*scaleWidth - scaleTextWidth/2,  height() - bottomBorder + scaleTextBorder);node->scaleValue = startScaleValue + var*scaleValue;if(var%scaleCntShowText == 0){node->pointScaleTwo = QPointF((double)(leftBorder + var*scaleWidth), height() - bottomBorder - scaleTextScaleLength);node->bShowScaleText = true;}var++;node = node->nextNode;}}void CharView::InitScaleNode()
{bPressRightMove = false;bPressLeft = false;bPressRight = false;bShowCursor = true;leftBorder = 50;topBorder = 10;rightBorder = 50;bottomBorder = 20;scaleCntShowText = 5;startScaleValueInit = 0;endScaleValueInit = 3000000000;startScaleValue = startScaleValueInit;endScaleValue = endScaleValueInit;scaleCnt = 30;scaleLength = 2;scaleTextScaleLength = 4;scaleTextBorder = 5;scaleTextWidth = 100;scaleTextHeight = fontMetrics().height();ScaleNode* nodeTmp=nullptr;for (int var = 0; var <= scaleCnt; ++var) {ScaleNode* node = new ScaleNode;if(nodeTmp)nodeTmp->nextNode = node;nodeTmp = node;if(var == 0)scaleNodeBegin = node;}
}void CharView::MouseWheelUpdateStartEndValue(int flag)
{double zoomValue = (endScaleValue - startScaleValue)/10;if(flag > 0){endScaleValue -= zoomValue;}else{endScaleValue += zoomValue;}double everyWidthValueOld = everyWidthValue;double centerX = currentPointF.x() - leftBorder;everyWidthValue = ((double)(endScaleValue - startScaleValue))/(width() - leftBorder - rightBorder);startScaleValue = startScaleValue + centerX*everyWidthValueOld - centerX*everyWidthValue ;endScaleValue = endScaleValue + centerX*everyWidthValueOld - centerX*everyWidthValue ;if(startScaleValue <=0)startScaleValue = 0;
}void CharView::MouseLeftMoveUpdateStartEndValue()
{double offsetX  =  currentPointF.x() - pressPointF.x();pressPointF = currentPointF;double offsetValue = offsetX*everyWidthValue;if(startScaleValue - offsetValue <=0 && offsetX > 0){startScaleValue = 0;offsetValue = startScaleValue;}else{startScaleValue = startScaleValue - offsetValue;}endScaleValue = endScaleValue - offsetValue;}void CharView::MouseRightMoveUpdateStartEndValue()
{if(currentPointF.x() < leftBorder || currentPointF.x() > width() - rightBorder ||pressPointF.x() < leftBorder || pressPointF.x() > width() - rightBorder|| !bPressRight)return;endScaleValue = startScaleValue + (currentPointF.x() - leftBorder)*everyWidthValue;startScaleValue = startScaleValue + (pressPointF.x() - leftBorder)*everyWidthValue;
}void CharView::paintEvent(QPaintEvent *event)
{//界面大小改变,只改变刻度实际宽度, 刻度开始结束值不变//鼠标缩放,刻度实际宽度改变, 刻度开始结束值改变//鼠标拖动,刻度实际宽度不变, 刻度开始结束值改变//绘制前计算更新刻度UpdeScaleNode();QPainter painter(this);// painter.setRenderHint(QPainter::Antialiasing);//加上会加粗//绘制游标paintAxisX(painter);paintAxisY(painter);//绘制数据paintData(painter);paintMouseRightMove(painter);//绘制游标if(bShowCursor)paintCursor(painter);
}void CharView::paintMouseRightMove(QPainter &painter)
{if(currentPointF.x() < leftBorder || currentPointF.x() > width() - rightBorder ||pressPointF.x() < leftBorder || pressPointF.x() > width() - rightBorder|| !bPressRight)return;QPen pen;pen.setStyle(Qt::DashLine);pen.setColor(QColor(236,132,251));pen.setWidth(1);painter.setPen(pen);double w = currentPointF.x() - pressPointF.x();double y = currentPointF.y() - pressPointF.y();painter.drawRect(pressPointF.x(),pressPointF.y(), w, y);
}void CharView::paintAxisX(QPainter &painter)
{QPen pen;pen.setStyle(Qt::SolidLine);pen.setColor(Qt::black);pen.setWidth(1);painter.setPen(pen);int y = height() - bottomBorder;painter.drawLine(QPointF(leftBorder, y),QPointF(width() - rightBorder, y));ScaleNode* node = scaleNodeBegin;while(node){painter.drawLine(node->pointScaleOne,node->pointScaleTwo);if(node->bShowScaleText)painter.drawText(node->pointScaleText.x(), node->pointScaleText.y(), scaleTextWidth, scaleTextHeight,Qt::AlignCenter, QString::number(node->scaleValue, 'f', 0));node = node->nextNode;}
}void CharView::paintAxisY(QPainter &painter)
{}void CharView::paintCursor(QPainter &painter)
{if(currentPointF.x() < leftBorder || currentPointF.x() > width() - rightBorder)return;QPen pen;pen.setStyle(Qt::DashLine);pen.setColor(QColor(236,132,251));pen.setWidth(1);painter.setPen(pen);painter.drawLine(QPointF(currentPointF.x(), 0), QPointF(currentPointF.x(), height() - bottomBorder));double number = (currentPointF.x() - leftBorder)*everyWidthValue + startScaleValue;painter.drawText(currentPointF.x(), height() - bottomBorder - scaleTextHeight, scaleTextWidth, scaleTextHeight,Qt::AlignLeft, QString::number(number, 'f', 0));
}void CharView::paintData(QPainter &painter)
{//testdouble value1 = 1240000000;double value2 = 1590000000;double x1 = leftBorder + (value1 - startScaleValue)/everyWidthValue;double x2 = leftBorder + (value2 - startScaleValue)/everyWidthValue;QPointF point1(x1, 100);QPointF point2(x2, 200);QPen pen;pen.setStyle(Qt::SolidLine);pen.setColor(Qt::black);pen.setWidth(1);painter.setPen(pen);painter.drawLine(point1,point2);
}void CharView::resizeEvent(QResizeEvent *event)
{UpdeScaleNode();return QWidget::resizeEvent(event);
}void CharView::mouseMoveEvent(QMouseEvent *event)
{currentPointF = event->localPos();if(bPressLeft){if(currentPointF != pressPointF)MouseLeftMoveUpdateStartEndValue();}else if(bPressRight){bPressRightMove = true;}update();return QWidget::mouseMoveEvent(event);
}void CharView::mousePressEvent(QMouseEvent *event)
{if(!bPressLeft && event->button() == Qt::LeftButton){bPressLeft = true;pressPointF = event->localPos();}else if(!bPressRight && event->button() == Qt::RightButton){bPressRight = true;pressPointF = event->localPos();}return QWidget::mousePressEvent(event);
}void CharView::mouseReleaseEvent(QMouseEvent *event)
{if(bPressRight){if(bPressRightMove && currentPointF != pressPointF)MouseRightMoveUpdateStartEndValue();bPressRight = false;bPressRightMove = false;update();}bPressLeft = false;return QWidget::mouseReleaseEvent(event);
}void CharView::wheelEvent(QWheelEvent *event)
{MouseWheelUpdateStartEndValue(event->delta());update();return QWidget::wheelEvent(event);
}void CharView::mouseDoubleClickEvent(QMouseEvent *event)
{startScaleValue = startScaleValueInit;endScaleValue = endScaleValueInit;return QWidget::mouseDoubleClickEvent(event);
}

相关文章:

Qt基于paintEvent自定义CharView

Qt基于paintEvent自定义CharView 鼠标拖动&#xff0c;缩放&#xff0c;区域缩放&#xff0c; 针对x轴&#xff0c;直接上代码 charview.h #ifndef CHARVIEW_H #define CHARVIEW_H#include <QWidget> #include <QPainter> #include <QPaintEvent> #inclu…...

Mac FoneLab for Mac:轻松恢复iOS数据,专业工具助力生活

如果你曾经不小心删除了重要的iOS数据&#xff0c;或者因为各种原因丢失了这些数据&#xff0c;那么你一定知道这种痛苦。现在&#xff0c;有一个名为Mac FoneLab的Mac应用程序&#xff0c;它专门设计用于恢复iOS数据&#xff0c;这可能是你的救星。 Mac FoneLab for Mac是一种…...

代码随想录二刷day30

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、力扣332. 重新安排行程二、力扣51. N 皇后三、力扣37. 解数独 一、力扣332. 重新安排行程 class Solution {private LinkedList<String> res;private Li…...

工业检测 ocr

采用OpenCV和深度学习的钢印识别_菲斯奇的博客-CSDN博客采用OpenCV和深度学习的钢印识别[这个帖子标题党了很久&#xff0c;大概9月初立贴&#xff0c;本来以为比较好做&#xff0c;后来有事情耽搁了&#xff0c;直到现在才有了一些拿得出手的东西。肯定不会太监的。好&#xf…...

LVS负载均衡群集

这里写目录标题 LVS负载均衡群集一.集群cluster与分布式1.特点&#xff1a;2.类型1&#xff09;负载均衡群集 LB2&#xff09;高可用群集 HA3&#xff09;高性能运输群集 HPC 3.分布式1&#xff09;特点 二.LVS1.lvs的工作原理2.lvs的三种工作模式1&#xff09;NAT 地址转换2&a…...

安卓截屏;前台服务

private var mediaProjectionManager: MediaProjectionManager? nullval REQUEST_MEDIA_PROJECTION 10001private var isstartservice true//启动MediaService服务fun startMediaService() {if (isstartservice) {startService(Intent(this, MediaService::class.java))iss…...

C++ PrimerPlus 复习 第八章 函数探幽

第一章 命令编译链接文件 make文件 第二章 进入c 第三章 处理数据 第四章 复合类型 &#xff08;上&#xff09; 第四章 复合类型 &#xff08;下&#xff09; 第五章 循环和关系表达式 第六章 分支语句和逻辑运算符 第七章 函数——C的编程模块&#xff08;上&#xff…...

JavaScript-Ajax-axios-Xhr

JS的异步请求 主要有xhr xmlHttpRequest 以及axios 下面给出代码以及详细用法&#xff0c;都写在了注释里 直接拿去用即可 测试中默认的密码为123456 账号admin 其他一律返回登录失败 代码实例 <!DOCTYPE html> <html lang"en"> <head><…...

怎样查看kafka写数据送到topic是否成功

要查看 Kafka 写数据是否成功送到主题&#xff08;topic&#xff09;&#xff0c;可以通过以下几种方法来进行确认&#xff1a; Kafka 生产者确认机制&#xff1a;Kafka 提供了生产者的确认机制&#xff0c;您可以在创建生产者时设置 acks 属性来控制确认级别。常见的确认级别包…...

腾讯mini项目-【指标监控服务重构】2023-08-16

今日已办 v1 验证 StageHandler 在处理消息时是否为单例&#xff0c;【错误尝试】 type StageHandler struct { }func (s StageHandler) Middleware1(h message.HandlerFunc) message.HandlerFunc {return func(msg *message.Message) ([]*message.Message, error) {log.Log…...

PTA:7-3 两个递增链表的差集

^两个递增链表的差集 题目输入样例输出样例 代码 题目 输入样例 5 1 3 5 7 9 3 2 3 5输出样例 3 1 7 9代码 #include <iostream> #include <list> #include <unordered_set> using namespace std; int main() {int n1, n2;cin >> n1;list<int&g…...

智能合约漏洞案例,DEI 漏洞复现

智能合约漏洞案例&#xff0c;DEI 漏洞复现 1. 漏洞简介 https://twitter.com/eugenioclrc/status/1654576296507088906 2. 相关地址或交易 https://explorer.phalcon.xyz/tx/arbitrum/0xb1141785b7b94eb37c39c37f0272744c6e79ca1517529fec3f4af59d4c3c37ef 攻击交易 3. …...

Attention is all you need 论文笔记

该论文引入Transformer&#xff0c;主要核心是自注意力机制&#xff0c;自注意力&#xff08;Self-Attention&#xff09;机制是一种可以考虑输入序列中所有位置信息的机制。 RNN介绍 引入RNN为了更好的处理序列信息&#xff0c;比如我 吃 苹果&#xff0c;前后的输入之间是有…...

Hdoop伪分布式集群搭建

文章目录 Hadoop安装部署前言1.环境2.步骤3.效果图 具体步骤&#xff08;一&#xff09;前期准备&#xff08;1&#xff09;ping外网&#xff08;2&#xff09;配置主机名&#xff08;3&#xff09;配置时钟同步&#xff08;4&#xff09;关闭防火墙 &#xff08;二&#xff09…...

java临时文件

临时文件 有时候&#xff0c;我们程序运行时需要产生中间文件&#xff0c;但是这些文件只是临时用途&#xff0c;并不做长久保存。 我们可以使用临时文件&#xff0c;不需要长久保存。 public static File createTempFile(String prefix, String suffix)prefix 前缀 suffix …...

C++中的<string>头文件 和 <cstring>头文件简介

C中的<string>头文件 和 <cstring>头文件简介 在C中<string> 和 <cstring> 是两个不同的头文件。 <string> 是C标准库中的头文件&#xff0c;定义了一个名为std::string的类&#xff0c;提供了对字符串的操作如size()、length()、empty() 及字…...

安装MySQL

Centos7下安装MySQL详细步骤_centos7安装mysql教程_欢欢李的博客-CSDN博客...

输入学生成绩,函数返回最大元素的数组下标,求最高分学生成绩(输入负数表示输入结束)

scanfscore()函数用于输入学生的成绩 int scanfscore(int score[N])//输入学生的成绩 {int i -1;do {i;printf("输入学生成绩:");scanf("%d", &score[i]);} while (score[i] > 0);return i; } findmax()用于寻找最大值 int findmax(int score[N…...

常用音频接口:TDM,PDM,I2S,PCM

常用音频接口&#xff1a;TDM&#xff0c;PDM&#xff0c;I2S&#xff0c;PCM_tdm音频_沙漠的甲壳虫的博客-CSDN博客 I2S/PCM接口及音频codec_音频pcm接口模块设计-CSDN博客 2个TDM8功放调试ing_周龙(AI湖湘学派)的博客-CSDN博客 数字音频接口时序----IIS、TDM、PCM、PDM_td…...

git clone报错Failed to connect to github.com port 443 after 21055 ms:

git 设置代理端口号 git config --global http.proxy http://127.0.0.1:10085 和 git config --global https.proxy http://127.0.0.1:10085 然后就可以成功git clone hugging face的数据集了 如果是https://huggingface.co/datasets/shibing624/medical/tree/main 那么…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...