C#自定义曲线绘图面板
一、实现功能
1、显示面板绘制。
2、拖动面板,X轴、Y轴都可以拖动。
3、显示面板缩放,放大或者缩小。
4、鼠标在面板中对应的XY轴数值。
5、自动生成的数据数组,曲线显示。
6、鼠标是否在曲线上检测。
二、界面

拖动面板

鼠标在曲线上识别

三、部分功能代码实现
1、图形面板
/// <summary>/// 生成坐标系图片面板/// </summary>/// <returns></returns>public Bitmap DrawImage(){ImageBoardInit();return bitMap;}
/// <summary>/// 创建绘图面板-显示坐标系/// </summary>private void ImageBoardInit(){//1、绘制X、Y坐标轴if ((int)height != 0 && (int)width != 0) //做这个判断是因为在最小化的情况下width=0。{bitMap = new Bitmap((int)width, (int)height); //根据给定的高度和宽度创建一个位图图像} graphics = Graphics.FromImage(bitMap); //从指定的 objBitmap 对象创建 objGraphics 对象 (即在objBitmap对象中画图)//根据给定颜色(LightGray)填充图像的矩形区域 (背景)graphics.DrawRectangle(new Pen(boardColor, 1), 0, 0, width - 1, height - 1); //画边框graphics.FillRectangle(new SolidBrush(backColor), 1, 1, width - 2, height - 2); //填充边框//画X轴,注意图像的原始X轴和Y轴计算是以左上角为原点,向右和向下计算的xAxisPoint1.X = xSpace + xSliceBegin;xAxisPoint1.Y = (height / 2) + ySliceBegin; //xAxisPoint2.X = width;xAxisPoint2.Y = xAxisPoint1.Y;graphics.DrawLine(new Pen(new SolidBrush(axisColor), 2), xAxisPoint1, xAxisPoint2);//画Y轴yAxisPoint1.X = xSpace + xSliceBegin;yAxisPoint1.Y = height ;yAxisPoint2.X = xSpace + xSliceBegin;yAxisPoint2.Y = 0 ;graphics.DrawLine(new Pen(new SolidBrush(axisColor), 2), yAxisPoint1, yAxisPoint2);//2、面板标题//graphics.DrawString("曲线编辑器", new Font("宋体", fontSize), new SolidBrush(Color.Blue), new PointF(width / 2, ySpace / 2));//3、画X轴上刻度、刻度说明 xSlice = (width - xSpace ) / xSliceCount;ySlice = (height / 2) / (ySliceCount / 2);int tempCountX1 = (int)(- xSliceBegin / xSlice);int tempCountY1 = (int)Math.Abs((ySliceBegin / ySlice));tempCountX = tempCountX1 + xSliceCount;tempCountY = tempCountY1 + ySliceCount/2;//画网格虚线Pen penDashed = new Pen(new SolidBrush(Color.Black));penDashed.DashStyle = DashStyle.Dash;for (int i = 1; i < tempCountX + 1; i++){//X轴刻度虚线graphics.DrawLine(penDashed, new PointF(i * xSlice + xSpace + xSliceBegin, 0 ), new PointF(i * xSlice + xSpace + xSliceBegin, height));//X轴刻度值标识文字string xStr = (i * xSliceValue).ToString();int nStrLength = xStr.Length;graphics.DrawString(xStr, new Font("宋体", fontSize), new SolidBrush(Color.Black), new PointF(i * xSlice + xSpace - fontSize * nStrLength + xSliceBegin, height / 2 + fontSize + ySliceBegin));}//Y轴虚线、刻度文字-正半轴for (int i = 0; i < tempCountY + 1; i++){graphics.DrawLine(penDashed, new PointF(xSpace + xSliceBegin, height / 2 - i * ySlice + ySliceBegin), new PointF(width, height / 2 - i * ySlice + ySliceBegin));//Y轴刻度值标识文字string yStr = (i * ySliceValue).ToString();int nStrLength = yStr.Length;if(i>0)graphics.DrawString(yStr, new Font("宋体", fontSize), new SolidBrush(Color.Black), new PointF(xSpace - fontSize * nStrLength + xSliceBegin, height / 2 - i * ySlice + ySliceBegin));}//Y轴虚线、刻度文字-负半轴for (int i = 1; i < tempCountY + 1; i++){graphics.DrawLine(penDashed, new PointF(xSpace + xSliceBegin, height / 2 + i * ySlice + ySliceBegin), new PointF(width, height / 2 + i * ySlice + ySliceBegin));//Y轴刻度值标识文字string yStr = (-i * ySliceValue).ToString();int nStrLength = yStr.Length;graphics.DrawString(yStr, new Font("宋体", fontSize), new SolidBrush(Color.Black), new PointF(xSpace - fontSize * nStrLength + xSliceBegin, height / 2 + i * ySlice + ySliceBegin));}//4、原点刻度说明graphics.DrawString("0", new Font("宋体", fontSize + 2), new SolidBrush(Color.Black), new PointF(xSpace - fontSize * 2 + xSliceBegin, height / 2 + ySliceBegin));}
2、数据点曲线显示
/// <summary>/// 绘制XY轴曲线/// </summary>/// <param name="xDatas">X轴数据</param>/// <param name="yDatas">Y轴数据</param>/// <param name="splineColor">曲线颜色</param>/// <param name="tension">曲线系数:0.0f-1.0f,默认0.5f,0.0f是直线</param>/// <param name="isPointFill">是否标出点</param>public void DrawXY(float[] xDatas,float[] yDatas,Color splineColor,float tension,bool isPointFill){int xLength = xDatas.Length;int yLength = yDatas.Length;if(xLength!=yLength){graphics.DrawString("X和Y数据长度不相等",new Font("宋体", fontSize + 5), new SolidBrush(Color.Blue), new Point((int)xSpace, (int)(height / 2)));return;}PointF[] splinePoints = new PointF[xDatas.Length];float xSlicePos = 0, ySlicePos = 0; //转换后的点在Image面板上像素点位置Brush brushPoint = new SolidBrush(splineColor); //数据点画刷for(int i=0;i<xDatas.Length;i++){xSlicePos = xSliceBegin + xSpace + xDatas[i] * xSlice / xSliceValue;ySlicePos = ySliceBegin + height / 2 - yDatas[i] * ySlice / ySliceValue;splinePoints[i] = new PointF(xSlicePos, ySlicePos);if (isPointFill){//graphics.FillEllipse(brushPoint, xSlicePos - 4, ySlicePos - 4, 8, 8); //原点graphics.FillRectangle(brushPoint, xSlicePos - 4, ySlicePos - 4, 8, 8); //矩形} }graphics.DrawCurve(new Pen(splineColor, 2.0f), splinePoints, tension);//graphics.Dispose();}
3、鼠标当前所在面板位置对应的坐标系统XY值
int ex = 0, ey = 0;int mouseToValueX = 0;float mouseToValueY = 0; //鼠标位置当前值float fMouseToValueX = 0;private void pictureBox1_MouseMove(object sender, MouseEventArgs e){ex = e.X;ey = e.Y;//1、显示鼠标在坐标系内X、Y对应的值fMouseToValueX =cureDraw.MousePosToValue_X(ex);mouseToValueX = (int)Math.Round(cureDraw.MousePosToValue_X(ex));//mouseToValueY = (float)Math.Round(cureDraw.MousePosToValue_Y(ey));mouseToValueY = cureDraw.MousePosToValue_Y(ey);if (mouseToValueX<0){mouseToValueX = 0;}if (mouseToValueX >= 0 && ex < pictureBox1.Width - 60){ labMousePos.Text = "X:" + mouseToValueX.ToString() + ";" + "Y:" + mouseToValueY.ToString();labMousePos.Location = new Point(ex + 50, ey + 40);}if (mouseToValueX >= 0 && ex > pictureBox1.Width - 60){ labMousePos.Text = "X:" + mouseToValueX.ToString() + ";" + "Y:" + mouseToValueY.ToString();labMousePos.Location = new Point(ex - 50, ey + 40);}}
4、鼠标是否在曲线上检测
bool isMouseOn = false;private void timer1_Tick(object sender, EventArgs e){//bool isMouseOn = cureDraw.IsMouseOnPointCheck(xDatas, yDatas, ex, ey);//bool isMouseOn = cureDraw.IsMouseOnPointCheck(xDatasExpand, yDatasExpand, ex, ey);float tempX = 0, tempY = 0;int n = 0;bool b1 = false, b2 = false;foreach (var xData in xDatasExpand){if(Math.Abs(xData-fMouseToValueX)<0.02){tempX = xData;}}for (int i = 0; i < xDatasExpand.Length;i++ ){if(xDatasExpand[i]==tempX){n = i;}}if (Math.Abs(yDatasExpand[n] - mouseToValueY)<2.5){isMouseOn = true;}else{isMouseOn = false;}txtValue1.Text = xDatasExpand[n].ToString(); //YtxtValue2.Text = fMouseToValueX.ToString();txtValue3.Text = yDatasExpand[n].ToString(); //XtxtValue4.Text = mouseToValueY.ToString();txtValue5.Text = n.ToString();if (isMouseOn){labMousePos.ForeColor = Color.Red; }else{labMousePos.ForeColor = Color.Black;}}
四、、工程下载链接
https://download.csdn.net/download/panjinliang066333/89775386
相关文章:
C#自定义曲线绘图面板
一、实现功能 1、显示面板绘制。 2、拖动面板,X轴、Y轴都可以拖动。 3、显示面板缩放,放大或者缩小。 4、鼠标在面板中对应的XY轴数值。 5、自动生成的数据数组,曲线显示。 6、鼠标是否在曲线上检测。 二、界面 拖动面板 鼠标在曲线上…...
Java后端面试题+下一篇答案+实况场景题
uu们大家好!市面上面试题很多,这边汇总并更新一下java后端面试的题目,助大家早日斩下心仪的offer!!(下次跟新场景题...等我多碰几次壁...哈哈哈哈哈) 这边放题目,下一篇跟新所有另面…...
完美解决vant浮动气泡+弹出菜单
使用框架: vue3,vant4 项目需求: 需要有一个浮动气泡,点击弹出导航菜单 遇到的问题: 1. 使用van-floating-bubble包裹van-popover,但点击后只会重复显示不能隐藏 2. popover位置固定,不能根据…...
SpringSecurity -- 入门使用
文章目录 什么是 SpringSesurity ?细节使用方法 什么是 SpringSesurity ? 在我们的开发中,安全还是有些必要的 用 拦截器 和 过滤器 写代码还是比较麻烦。 SpringSecurity 是 SpringBoot 的底层安全默认选型。一般我们需要认证和授权…...
C语言习题~day33
1.以下程序运行时,若输入1abcedf2df输出结果是() #include <stdio.h> int main() { char a 0, ch; while ((ch getchar()) ! \n) { if (a % 2 ! 0 && (ch > a && ch < z)) ch ch - a A; a; putchar(ch); }…...
作业报告┭┮﹏┭┮(Android反调试)
一:Android反调试 主要是用来防止IDA进行附加的,主要的方法思路就是,判断自身是否有父进程,判断是否端口被监听,然后通过调用so文件中的线程进行监视,这个线程开启一般JNI_OnLoad中进行开启的。但是这个是…...
在 Delphi BSD11中安装 DCU 格式的第三方组件库
在 Delphi BSD 11 中安装 DCU 格式的第三方组件库可以按照以下步骤进行: 打开 Delphi:启动 Delphi 开发环境。 选择安装组件: 在菜单栏中,选择 Component -> Install Component。 选择 DCU 文件: 在弹出的对话框中…...
综合题第二题(路由器的配置)
题目 如何计算子网掩码 第一类 我们可以观察到上图的IP地址后面有“/26”、“30”。我们都知道子网掩码是由多个连续“1”和多个连续“0”组成的,“、26”表示子网掩码的二进制表达中有26个1。 例如:156.95.9.128/26 1111 1111.1111 1111.1111 1111.1…...
人工智能概览
目录 什么是人工智能 人工智能的历史与发展 人工智能发展时间轴示意图: 人工智能的主要分支 机器学习与深度学习在AI中的地位 什么是人工智能 人工智能(Artificial Intelligence, AI)是指由人制造出来的具有一定智能的系统,能够理…...
[vulnhub] Prime 1
https://www.vulnhub.com/entry/prime-1,358/ 主机发现端口扫描 探测存活主机,137是靶机 nmap -sP 192.168.75.0/24 // Starting Nmap 7.93 ( https://nmap.org ) at 2024-09-22 16:25 CST Nmap scan report for 192.168.75.1 Host is up (…...
JavaSE——lombok、juint单元测试、断言
一、lombok的使用 默认jvm不解析第三方注解,需要手动开启 链式调用 二、juint单元测试 下载juint包 public class TestDemo {// 在每一个单元测试方法执行之前执行Beforepublic void before() {// 例如可以在before部分创建IO流System.out.println("befor…...
商标价值如何评估与增值?
商标是企业的标志,代表着企业的产品或服务质量、信誉和形象。一个具有高知名度和美誉度的商标,能够为企业带来巨大的商业价值。它不仅可以帮助企业在市场中脱颖而出,吸引消费者的关注和购买,还可以作为企业的重要资产进行融资、并…...
linux命令之firewall-cmd用法
firewall-cmd Linux上新用的防火墙软件,跟iptables差不多的工具 补充说明 firewall-cmd 是 firewalld的字符界面管理工具,firewalld是centos7的一大特性,最大的好处有两个:支持动态更新,不用重启服务;第…...
深入浅出CSS盒子模型
“批判他人总是想的太简单 剖析自己总是想的太困难” 文章目录 前言文章有误敬请斧正 不胜感恩!什么是盒子模型?盒子模型的组成部分详解1. 内容区(Content)2. 内边距(Padding)3. 边框(Border&am…...
字符编码发展史4 — Unicode与UTF-8
上一篇《字符编码发展史3 — GB2312/Big5/GBK/GB18030》我们讲解了ANSI编码中的GB2312/Big5/GBK/GB18030。本篇我们将继续讲解字符编码的第三个发展阶段中的Unicode与UTF-8。 2.3. 第三个阶段 国际化 前面提到的第二个阶段,各个国家和地区各自为政,纷纷…...
【flink】之如何消费kafka数据并读写入redis?
背景: 最近公司出现做了一个新需求,需求内容是加工一个营销时机,但是加工营销时机的同时需要把数据内容里的一个idmapping存入redis用于后续的读写。 准备: <!-- 依赖 --><dependency><groupId>org.apache.fl…...
搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(二)-索引
场景 首先介绍测试的场景,本系列schema定义 pdm文档索引,包括nested,作为文档扩展属性字段,_content字段是组件保留字段,支持文本内容,字段属性还有其他属性,如boost,getter&#x…...
离散化算法
离散化 在C中,离散化通常指的是将连续的数值或数据转化为离散的形式。这在数值分析、信号处理、图像处理和机器学习等领域都非常常见。以下是一些离散化的基本概念和方法: 1.区间划分: 将连续变量的值域分成多个区间,每个区间对…...
基于ollama的本地RAG实践
先放参考的原文链接大语言模型实战——搭建纯本地迷你版RAG_本地rag-CSDN博客 一、大模型选择 在我之前的文章中有讲到,我用的是ollama中的llama3.1 Ollama在Windows安装,使用,简单调用API_ollama如何对外提供api-CSDN博客 二、嵌入模型 …...
安卓开发板_MTK开发板_联发科开发评估套件Demo板接口介绍
开发板是一种功能丰富的电路平台,专为开发人员设计,集成了多种传感器、扩展接口和通信模块。这使得开发者能够高效进行原型设计和功能验证,极大地简化了软硬件开发的过程。 此次介绍的安卓开发板由MT8788核心板与底板构成,特别之处…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
