当前位置:
首页 > Python基础教程 >
-
C#教程之C# GDI绘制仪表盘(纯代码实现)
纯代码实现GDI绘制仪表盘,效果在代码下面。 public partial class HalfDashboardUc : UserControl { /// <summary> /// 仪表盘背景图片 /// </summary> private Image dashboardImage; /// <summary> /// 定义该仪表盘画布的最大值为371 /// </summary> private int maxSize = 371; /// <summary> /// 仪表盘画布的放大倍数,默认1 /// </summary> private float multiple = 1; /// <summary> /// 定义该仪表盘的直径大小 /// </summary> private float diameter; /// <summary> /// 每个间隔值 /// </summary> private int intervalValue; /// <summary> /// 仪表盘显示的最小值,默认为0 /// </summary> private float minValue = 0; /// <summary> /// 仪表盘显示的最小值 /// </summary> [Category("wyl")] [Description("仪表盘显示的最小值")] public float MinValue { get { return minValue; } set { if (value >= MaxValue) { MessageBox.Show("最小值不能超过最大值!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); minValue = 0; } else { minValue = value; //drawBackImage(); } } } /// <summary> /// 仪表盘上显示的最大值,默认123。 /// </summary> private float maxValue = 123; /// <summary> /// 仪表盘上显示的最大值 /// </summary> [Category("wyl")] [Description("仪表盘上显示的最大值")] public float MaxValue { get { return maxValue; } set { if (value <= MinValue) { MessageBox.Show("最大值不能低于最小值!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); maxValue = 123; } else { maxValue = value; //drawBackImage(); } } } // <summary> /// 仪表盘变换的值,默认为0; /// </summary> private float changeValue = 0; /// <summary> /// 仪表盘变换的值 /// </summary> public float ChangeValue { get { return changeValue; } set { changeValue = value; } } /// <summary> /// 指针颜色 /// </summary> private Color pinColor = Color.FromArgb(191, 148, 28); public Color PinColor { get { return pinColor; } set { pinColor = value; } } public HalfDashboardUc() { InitializeComponent(); //双缓存防止屏幕抖动 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.UserPaint, true); this.UpdateStyles(); //设置背景颜色为透明 this.BackColor = Color.Transparent; } //private int uintfontsize = 40; /// <summary> /// 初始化仪表盘画布 /// </summary> private void InitialCanvas() { //对比控件的长高,以最小值为仪表盘的半径 if (this.Width > 2 * this.Height) { diameter = 2 * this.Height - 15; } else { diameter = this.Width - 15; } multiple = (float)diameter / maxSize;//计算仪表盘放大倍数 //如果半径大于仪表盘的最大值,则设定放大倍数为默认值 if (multiple > 1) { multiple = 1; diameter = maxSize; } intervalValue = (int)((MaxValue - minValue) / 3);//计算每个间隔之间的值 } /// <summary> /// 画底图 /// </summary> private void drawBackImage() { Bitmap bit = new Bitmap(this.Width, this.Height); Graphics gp = Graphics.FromImage(bit); gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; float radius = diameter / 2;//半径 float cerX = this.Width / 2; float cerY = this.Height / 2 + radius / 2 - 10 * multiple; //float cerY = this.Height - 20 ; gp.TranslateTransform(cerX, cerY);//以中心点为画布的起始点 //gp.DrawPie(new Pen(new SolidBrush(Color.FromArgb(19,20,25)),3), -radius, -radius, diameter, diameter, 175, 190); gp.DrawArc(new Pen(new SolidBrush(Color.FromArgb(19, 20, 25)), 3), -radius, -radius, diameter, diameter, 175, 190); float x1 = (float)((radius) * Math.Cos(175 * Math.PI / 180)); float y1 = (float)((radius) * Math.Sin(175 * Math.PI / 180)); float x2 = (float)((radius) * Math.Cos(5 * Math.PI / 180)); float y2 = (float)((radius) * Math.Sin(5 * Math.PI / 180)); gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(19, 20, 25)), 3), x1, y1, x2, y2); //gp.DrawEllipse(new Pen(Brushes.Red), -5, -5, 10, 10); float startRad = 180;//起始角度 float sweepShot = 0;//旋转角度 //gp.DrawLine(new Pen(Brushes.Red), -radius, 0, -(radius - 10), 0); for (int i = 0; i <= 30; i++) { double rad = (sweepShot + startRad) * Math.PI / 180; if (i % 5 == 0) { float px1 = (float)((radius - 5 ) * Math.Cos(rad)); float py1 = (float)((radius - 5 ) * Math.Sin(rad)); float px2 = (float)((radius - 15) * Math.Cos(rad)); float py2 = (float)((radius - 15) * Math.Sin(rad)); gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(122, 179, 222)), 2), px1, py1, px2, py2); } else { float px1 = (float)((radius - 5 ) * Math.Cos(rad)); float py1 = (float)((radius - 5 ) * Math.Sin(rad)); float px2 = (float)((radius - 10 ) * Math.Cos(rad)); float py2 = (float)((radius - 10 ) * Math.Sin(rad)); gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(77, 88, 124)), 1), px1, py1, px2, py2); } sweepShot += 6; } //刻度字体 Font scaleFont = new Font("宋体", 9, FontStyle.Bold); startRad = 270;//起始角度 sweepShot = 0;//旋转角度 Color c1 = Color.FromArgb(0, 192, 0); for (int i = 0; i < 4; i++) { int tempValue = i * intervalValue; SizeF tempSf = gp.MeasureString(tempValue.ToString(), scaleFont); //计算角度值 double rad = (sweepShot + startRad) * Math.PI / 180; float px = (float)((radius - 18) * Math.Cos(rad)); float py = (float)((radius - 18) * Math.Sin(rad)); if (sweepShot == 0) { gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Wheat, px - tempSf.Width / 2, py); } else if (sweepShot == 30) { gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width + 5 * multiple, py - tempSf.Height / 2 + 10 * multiple); } else if (sweepShot == 60) { gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / 2 + 5 * multiple); } else if (sweepShot == 90) { gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / 2); } //else if (sweepShot == 120) //{ // gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / 2); //} sweepShot += 30; } startRad = 270;//起始角度 sweepShot = 0;//旋转角度 for (int i = 0; i < 4; i++) { int tempValue = -i * intervalValue; SizeF tempSf = gp.MeasureString(tempValue.ToString(), scaleFont); //计算角度值 double rad = (sweepShot + startRad) * Math.PI / 180; float px = (float)((radius - 18 * multiple) * Math.Cos(rad)); float py = (float)((radius - 18 * multiple) * Math.Sin(rad)); if (sweepShot == -30) { gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px, py + tempSf.Height / 2); } else if (sweepShot == -60) { gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px + tempSf.Width / 2 - 10 * multiple, py + tempSf.Height / 2 - 5 * multiple); } else if (sweepShot == -90) { gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px + tempSf.Width/2 , py - tempSf.Height / 2); } sweepShot -= 30; } gp.Dispose(); this.BackgroundImage = bit; } /// <summary> /// 画图 /// </summary> /// <param name="g"></param> private void DrawPin(Graphics g) { Bitmap bit = new Bitmap(this.Width, this.Height); Graphics gp = Graphics.FromImage(bit); gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; float radius = diameter / 2;//半径 float startRad = 270;//起始角度 float sweepShot = (float)(ChangeValue / MaxValue * 90);//旋转角度 float cerX = this.Width / 2; float cerY = this.Height / 2 + radius / 2 - 10 * multiple; gp.TranslateTransform(cerX, cerY);//以中心点为画布的起始点 //gp.DrawEllipse(new Pen(PinColor, 1), -5, -5, 10, 10);//画中心圆圈 double rad = (sweepShot + startRad) * Math.PI / 180;//计算角度 float px = (float)((radius - 15) * Math.Cos(rad)); float py = (float)((radius - 15) * Math.Sin(rad)); PointF[] pf = new PointF[] { new PointF(0, -radius + 15), new PointF(-4, 0), new PointF(4, 0) }; gp.RotateTransform(sweepShot); //PointF[] pf = new PointF[] { new PointF(px, py), new PointF(-4, 0), new PointF(4, 0) }; gp.FillPolygon(new SolidBrush(PinColor), pf); //gp.DrawLine(new Pen(new SolidBrush(PinColor), 3f), 0, 0, px, py); g.DrawImage(bit, 0, 0); gp.Dispose(); } private void HalfDashboardUc_Load(object sender, EventArgs e) { InitialCanvas(); drawBackImage(); } private void HalfDashboardUc_Paint(object sender, PaintEventArgs e) { DrawPin(e.Graphics); } private void HalfDashboardUc_Resize(object sender, EventArgs e) { InitialCanvas(); drawBackImage(); } }
效果实现如下:
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式