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

.net 8 C# WinForms GDI+ 绘制曲线图形

usingSystem;usingSystem.Collections.Generic;usingSystem.Drawing;usingSystem.Drawing.Drawing2D;usingSystem.Windows.Forms;namespaceWinFormsApp2{publicpartialclassForm1:Form{// 存储实时数据的集合privateList<int>_dataPoints=newList<int>();// 绘图区域的尺寸和边距privatereadonlyint_paddingLeft=40;// 左内边距(纵轴文字)privatereadonlyint_paddingRight=10;// 右内边距privatereadonlyint_paddingTop=10;// 上内边距privatereadonlyint_paddingBottom=30;// 下内边距(横轴文字)// 坐标系参数privatereadonlyint_maxYValue=100;// Y轴最大值privatereadonlyint_minYValue=0;// Y轴最小值(X轴对应值)privatereadonlyint_xAxisMaxPoints=40;// X轴最大显示点数(0-40)privatereadonlyint_gridIntervalY=20;// Y轴网格线间隔privatereadonlyint_gridIntervalX=5;// X轴网格线间隔// 定时器(模拟实时数据)privateSystem.Windows.Forms.Timer_dataTimer;publicForm1(){InitializeComponent();InitForm();InitTimer();}/// <summary>/// 初始化窗体和绘图面板/// </summary>privatevoidInitForm(){this.Text="实时折线图(GDI+)";this.Size=newSize(800,600);// 创建绘图面板PanelchartPanel=newPanel();chartPanel.Dock=DockStyle.Fill;chartPanel.BackColor=Color.White;chartPanel.Paint+=ChartPanel_Paint;// 绑定绘制事件this.Controls.Add(chartPanel);}/// <summary>/// 初始化定时器(模拟每秒添加一个随机数据)/// </summary>privatevoidInitTimer(){_dataTimer=newSystem.Windows.Forms.Timer();_dataTimer.Interval=1000;// 1秒触发一次_dataTimer.Tick+=(s,e)=>{Randomrandom=newRandom();intnewData=random.Next(_minYValue,_maxYValue);AddRealTimeData(newData);};_dataTimer.Start();}/// <summary>/// 添加实时数据并刷新绘图/// </summary>/// <param name="value">新数据值</param>publicvoidAddRealTimeData(intvalue){// 强制数据≥X轴对应的值(0)intvalidValue=Math.Max(value,_minYValue);_dataPoints.Add(validValue);// 严格限制数据长度为_xAxisMaxPoints,避免超界if(_dataPoints.Count>_xAxisMaxPoints){_dataPoints.RemoveAt(0);}this.Controls[0].Invalidate();}/// <summary>/// 核心绘制逻辑/// </summary>privatevoidChartPanel_Paint(objectsender,PaintEventArgse){Panelpanel=senderasPanel;if(panel==null)return;// 开启双缓冲,避免绘图闪烁e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;e.Graphics.Clear(Color.White);// 计算实际绘图区域(扣除边距)RectangledrawArea=newRectangle(_paddingLeft,_paddingTop,panel.Width-_paddingLeft-_paddingRight,panel.Height-_paddingTop-_paddingBottom);// 1. 绘制网格线DrawGridLines(e.Graphics,drawArea);// 2. 绘制坐标轴DrawAxis(e.Graphics,drawArea);// 3. 绘制折线(至少2个点才绘制)if(_dataPoints.Count>=2){DrawLineChart(e.Graphics,drawArea);}}/// <summary>/// 绘制网格线/// </summary>privatevoidDrawGridLines(Graphicsg,RectangledrawArea){PengridPen=newPen(Color.LightGray,1);// Y轴网格线(水平)floatyStep=drawArea.Height/(float)(_maxYValue-_minYValue)*_gridIntervalY;for(inty=_gridIntervalY;y<_maxYValue;y+=_gridIntervalY){floatyPos=drawArea.Bottom-(y-_minYValue)*(drawArea.Height/(float)(_maxYValue-_minYValue));g.DrawLine(gridPen,drawArea.Left,yPos,drawArea.Right,yPos);}// X轴网格线(垂直)floatxStep=drawArea.Width/(float)_xAxisMaxPoints*_gridIntervalX;for(intx=_gridIntervalX;x<_xAxisMaxPoints;x+=_gridIntervalX){floatxPos=drawArea.Left+x*(drawArea.Width/(float)_xAxisMaxPoints);g.DrawLine(gridPen,xPos,drawArea.Top,xPos,drawArea.Bottom);}gridPen.Dispose();}/// <summary>/// 绘制坐标轴(X/Y轴 + 刻度文字)/// </summary>privatevoidDrawAxis(Graphicsg,RectangledrawArea){PenaxisPen=newPen(Color.Black,2);FontaxisFont=newFont("Arial",8);BrushtextBrush=Brushes.Black;// 绘制Y轴(纵轴)g.DrawLine(axisPen,drawArea.Left,drawArea.Top,drawArea.Left,drawArea.Bottom);// Y轴刻度文字for(inty=_minYValue;y<=_maxYValue;y+=_gridIntervalY){floatyPos=drawArea.Bottom-(y-_minYValue)*(drawArea.Height/(float)(_maxYValue-_minYValue));stringyText=y.ToString();SizeFtextSize=g.MeasureString(yText,axisFont);g.DrawString(yText,axisFont,textBrush,drawArea.Left-textSize.Width-5,yPos-textSize.Height/2);}// 绘制X轴(横轴)g.DrawLine(axisPen,drawArea.Left,drawArea.Bottom,drawArea.Right,drawArea.Bottom);// X轴刻度文字for(intx=0;x<=_xAxisMaxPoints;x+=_gridIntervalX){// 核心校准:X轴刻度文字的坐标和折线坐标用同一套计算逻辑floatxPos=drawArea.Left+(x*drawArea.Width)/(float)_xAxisMaxPoints;stringxText=x.ToString();SizeFtextSize=g.MeasureString(xText,axisFont);g.DrawString(xText,axisFont,textBrush,xPos-textSize.Width/2,drawArea.Bottom+5);}axisPen.Dispose();axisFont.Dispose();}/// <summary>/// 绘制折线(彻底修复X轴超界问题)/// </summary>privatevoidDrawLineChart(Graphicsg,RectangledrawArea){PenlinePen=newPen(Color.Red,2);List<PointF>pointList=newList<PointF>();// 遍历数据点,精准映射坐标for(inti=0;i<_dataPoints.Count;i++){// #################### 核心修复 ####################// 原逻辑:x = drawArea.Left + i * (drawArea.Width / _xAxisMaxPoints)// 问题:当i=_xAxisMaxPoints时,x = drawArea.Left + drawArea.Width → 超出drawArea.Right// 新逻辑:按比例映射,i对应X轴刻度值(0~40),确保最后一个点落在drawArea.Rightfloatx=drawArea.Left+(i*drawArea.Width)/(float)_xAxisMaxPoints;// 双重兜底:确保X坐标不超出绘图区域x=Math.Clamp(x,drawArea.Left,drawArea.Right);// Y坐标计算(确保不低于X轴、不高于上边界)floaty=drawArea.Bottom-(_dataPoints[i]-_minYValue)*(drawArea.Height/(float)(_maxYValue-_minYValue));y=Math.Clamp(y,drawArea.Top,drawArea.Bottom);// 用Clamp简化边界限制pointList.Add(newPointF(x,y));}// 绘制折线g.DrawLines(linePen,pointList.ToArray());linePen.Dispose();}// 窗体关闭时停止定时器,释放资源protectedoverridevoidOnFormClosing(FormClosingEventArgse){_dataTimer?.Stop();_dataTimer?.Dispose();base.OnFormClosing(e);}}}
http://www.jsqmd.com/news/693717/

相关文章:

  • RPC 原理:Dubbo为了偷懒而存在的中间商
  • 无线通信‘抗衰’神器:用Python复现Alamouti编码,对比2x1与2x2 MIMO的误码率提升
  • 终极指南:在Windows电脑上直接运行安卓APK文件的完整解决方案
  • Ansible拆分大型Playbook
  • VSCode金融配置实战手册(券商/私募/自营团队内部流出版):支持Jupyter+QuantLib+FIX协议一键调试
  • Yakit WebFuzzer序列实战:巧用数据提取器和Nuclei DSL函数,动态处理上传路径
  • 2026椰制糖水品质鉴别技术:如何选到靠谱的糖水品牌 - 资讯焦点
  • 让macOS窗口变透明:提升工作效率的视觉革命
  • 别再只用@input了!UniApp搜索框实战:实时联想与回车确认的完整交互方案
  • 博德之门3模组管理器:轻松打造个性化游戏体验
  • TCP的建立与终止——三次握手、四次挥手
  • iperf3 Windows版终极指南:三步精准测量你的网络真实性能
  • 为什么说芬尼是空气能行业的 “极寒技术标杆”?41℃制热背后的技术密码 - 资讯焦点
  • 告别取模软件!用Python脚本为51单片机的8×8点阵自定义图案(附源码)
  • 最后50天,PMP还能过吗?能,只要你别把PMBOK当《圣经》啃
  • 2026年成绩发布工具权威测评:易查分综合表现极佳 20
  • 精读双模态检测论文十八|MambaRefine-YOLO创新点拉满!YOLO 即插即用涨点神器!!!!无人机小目标检测 SOTA,双门控 Mamba 融合 + 分层特征聚合暴力涨点!
  • 量子计算入门不踩坑(VSCode专属配置白皮书)
  • FreeRTOS事件组避坑指南:同步多个任务的正确姿势,我踩过的雷你别再踩
  • Spring Boot集成gRPC的基本使用
  • 告别手动抢购烦恼:Campus-imaotai智能茅台预约系统全攻略
  • 一生赴一约 经典耀东方 —— 马勇:以热爱传承传奇,以大爱联通世界 - 资讯焦点
  • 3、Frida源码逻辑梳理一(时序图)
  • 为什么你的嵌入式调试总出问题?试试给JLink加个电源和信号隔离吧
  • C++信奥洛谷循环章节练习题
  • 【MarkDown学习】
  • Unity_Shader实战:从顶点法线到屏幕空间的轮廓光进阶
  • Intv_AI_MK11 Qt图形界面开发:AI功能集成与界面设计
  • 终极指南:让你的Xbox手柄在Mac上重获新生 - 360Controller驱动实战手册
  • 给嵌入式新手的礼物:用Keil5软件仿真,零硬件调试你的第一个ARM汇编程序