zoukankan      html  css  js  c++  java
  • C# 制作 仪表

    以前在百度写的文档,转移到此处

    前些天在做NetAnalyzer时,需要使用一个指针仪表,网上看了一下,也有人做过,但是大部分都是收费的,本着自力更生的原则,于是决定自己设计一个,今天拿出来有读者分享一下。

    首先是截图:

    该仪表是以控件形式提供

    在开始之前还要赘述一点关于GDI+中角度的计算

    如下图

    在WinForm中左上角的点位(0,0),即原点,而其起始角则是图中划线处开始的,即为 rad=0;

    在绘图时,尤其是做过扇形统计图的人应该比较清楚。

    --------------------------------------------------------

    接下来就是正式开始

    首先新建控件,设置为witdth=height=150 ,可以自己定义,我在这里时可以自适应的

    将背景颜色设置为Transparent(透明色),方便以后使用时减少干扰

    在该仪表中主要分为两部分:背景部分(外框,刻度,单位等一些列基本不需要频繁变化的部分),前景部分(指针部分)

    所以为了不是两个图层不相互影响,我们将背景绘制在控件的BackgroundImage 属性上,而指针部分则需要一个pictrueBox控件作为载体。

    首先画背景

    在绘制背景时,又分为外框、刻度,指针固定中心等

      1   // 绘制背景 用来总体控制背景的绘制
      2         private void DrawBackImg()
      3         {
      4             Bitmap bit = new Bitmap(this.Width, this.Height);
      5             Graphics gp = Graphics.FromImage(bit);
      6             gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
      7             #region 在这里可以扩展需要绘制的背景项目
      8             //外框
      9             drawFrame(gp);
     10             // 画刻度
     11             DrawRuling(gp);
     12             //画点
     13             drawPoint(gp);
     14 
     15             //绘制单位
     16 
     17             DrawUnitStr(gp);
     18 
     19             #endregion
     20 
     21            //当绘制完成后,直接直接设置为背景
     22 
     23             this.BackgroundImage = bit;
     24         }
     25 
     26 
     27       //绘制单位
     28 
     29        private void DrawUnitStr(Graphics gp)
     30         {
     31             int cer = _diameter / 2;
     32             gp.DrawString(_unitStr, new Font("宋体", 10), new SolidBrush(_frameColor), new PointF(cer, (float)(cer - cer * 0.3)), strFormat);
     33 
     34         }
     35 
     36         /// <summary>
     37         /// 画外框
     38         /// </summary>
     39         /// <param name="gp"></param>
     40         private void drawFrame(Graphics gp)
     41         {
     42             Pen pen = new Pen(_frameColor, 2);
     43             Rectangle rec = new Rectangle(5, 5, _diameter - 10, _diameter - 10);
     44             gp.DrawEllipse(pen, rec);
     45         }
     46         // 画刻度  此次较为复杂,主要是在绘制刻度值时需要处理
     47         private void DrawRuling(Graphics gp)
     48         {
     49             //刻度
     50             int cerX = _diameter / 2;
     51             int cerY = _diameter / 2;
     52 
     53            //这里需要注意,因外在上面的图中标识了rad=0的位置,而我们的仪表时270度的,0点在135度处,
     54 
     55            //为了符合该效果所以起始位置设为135度。
     56             float start = 135;
     57             float sweepShot = 0;
     58             int dx = 0;
     59             int dy = 0;
     60             int soildLenght = 8;
     61             Pen linePen = new Pen(_frameColor, 1);
     62             float span = (float)(_maxValue / 30);
     63             float sp = 0;
     64             //用于右边数字右对齐
     65             StringFormat stf = new StringFormat();
     66             stf.Alignment = StringAlignment.Far;
     67 
     68             StringFormat stfMid = new StringFormat();
     69             stfMid.Alignment = StringAlignment.Center;
     70             stfMid.LineAlignment = StringAlignment.Center;
     71             for (int i = 0; i <= 30; i++)
     72             {
     73                 //注意此处,C#提供的三角函数计算中使用的弧度值,而此处获取的是角度值,需要转化
     74 
     75                 double rad = (sweepShot + start) * Math.PI / 180;
     76                 float radius = _diameter / 2 - 5;
     77                 int px = (int)(cerX + radius * Math.Cos(rad));
     78                 int py = (int)(cerY + radius * Math.Sin(rad));
     79                 if (sweepShot % 15 == 0)
     80                 {
     81                     linePen.Width = 2;
     82 
     83                    //计算刻度中的粗线
     84                     dx = (int)(cerX + (radius - soildLenght) * Math.Cos(rad));
     85                     dy = (int)(cerY + (radius - soildLenght) * Math.Sin(rad));
     86 
     87                     //绘制刻度值,注意字串对其方式
     88                     string str = sp.ToString("f0");
     89                     if (sweepShot <= 45)
     90                     {
     91                         gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy - 5));
     92                     }
     93                     else if (sweepShot > 45 && sweepShot < 135)
     94                     {
     95                         gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy));
     96                     }
     97                     else if (sweepShot == 135)
     98                     {
     99                         gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy + 10), stfMid);
    100                     }
    101                     else if (sweepShot > 135 && sweepShot < 225)
    102                     {
    103                         gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy), stf);
    104                     }
    105                     else if (sweepShot >= 225)
    106                     {
    107                         gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy - 5), stf);
    108                     }
    109 
    110                 }
    111                 else
    112                 {
    113 
    114                     //计算刻度中细线
    115 
    116                     linePen.Width = 1;
    117                     dx = (int)(cerX + (radius - soildLenght + 2) * Math.Cos(rad));
    118                     dy = (int)(cerY + (radius - soildLenght + 2) * Math.Sin(rad));
    119                 }
    120 
    121                  //绘制刻度线
    122                 gp.DrawLine(linePen, new Point(px, py), new Point(dx, dy));
    123                 sp += span;
    124                 sweepShot += 9;
    125             }
    126         }
    127         //画中间的点
    128         private void drawPoint(Graphics gp)
    129         {
    130             Pen p = new Pen(_frameColor);
    131             int tmpWidth = 6;
    132             int px = _diameter / 2 - tmpWidth;
    133 
    134             gp.DrawEllipse(p, new Rectangle(px, px, 2 * tmpWidth, 2 * tmpWidth));
    135 
    136             //在画点时,我使用了指针的颜色,这样看起来,更真实一点
    137             gp.FillEllipse(new SolidBrush(_pinColor), new Rectangle(px + 2, px + 2, 2 * tmpWidth - 4, 2 * tmpWidth - 4));
    138         }
    139 
    140 -------------------------------------------
    141 
    142 画指针
    143 
    144 绘制指正时,最大的问题就是界面闪速,除了在控件构造方法里添加如下代码:
    145 
    146         SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
    147         UpdateStyles();
    148 
    149 绘制方式也需要调整,方法如下:
    150 
    151  
    152 
    153   //为了方式绘制指针时产生的闪烁,PictureBox添加该事件方法 
    154 
    155         private void pic_Paint(object sender, PaintEventArgs e)
    156         {
    157               DrawForeImg(e.Graphics);
    158        }
    159 
    160       //使用方法
    161 
    162          public double ChangeValue
    163         {
    164             get { return _changeValue; }
    165             set
    166             {
    167                 if (value <= _maxValue)
    168                     _changeValue = value;
    169                 else
    170                 {
    171                     //完成自适应性
    172                     MaxValue = value;
    173                     _changeValue = value;
    174                 }
    175                //通过该方法,可以使指针自动绘制(其实就是强制重绘)
    176 
    177                pic.Invalidate();
    178             }
    179         }
    180 
    181         //指针的具体画法  
    182 
    183         private void DrawForeImg(Graphics gp)
    184         {
    185             Bitmap bit = new Bitmap(this.Width, this.Height);
    186             Graphics g = Graphics.FromImage(bit);
    187             g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
    188 
    189             //画针
    190             DrawPin(g);
    191             DrawString(g);
    192 
    193             //注意此处的绘制方式,这样可以有效减少界面的闪烁问题。
    194             gp.DrawImage(bit, new Point(0, 0));
    195             g.Dispose();
    196 
    197         }
    198         //画针
    199         private void DrawPin(Graphics g)
    200         {
    201             int cer = _diameter / 2;
    202             float start = 135;
    203             float sweepShot = (float)(_changeValue / _maxValue * 270);
    204 
    205             Pen linePen = new Pen(_pinColor, 1);
    206             Pen NxPen = new Pen(_pinColor, 2);
    207             Pen xPen = new Pen(_pinColor, 5);
    208             double rad = (sweepShot + start) * Math.PI / 180;
    209             float radius = _diameter / 2 - 5;
    210             int dx = (int)(cer + (_PinLen) * Math.Cos(rad));
    211             int dy = (int)(cer + (_PinLen) * Math.Sin(rad));
    212 
    213             int px = (int)(cer + (_PinLen * 0.4) * Math.Cos(rad));
    214             int py = (int)(cer + (_PinLen * 0.4) * Math.Sin(rad));
    215 
    216             int nx = (int)(cer - (NxPinLen) * Math.Sin(rad));
    217             int ny = (int)(cer - (NxPinLen) * Math.Cos(rad));
    218             g.DrawLine(linePen, new Point(cer, cer), new Point(dx, dy));
    219             g.DrawLine(NxPen, new Point(cer, cer), new Point(px, py));
    220             g.DrawLine(xPen, new Point(cer, cer), new Point(ny, nx));
    221         }
    222 
    223        //绘制在仪表下面的值
    224 
    225         private void DrawString(Graphics g)
    226         {
    227             int cer = _diameter / 2;
    228             string str = _changeValue.ToString("F2");
    229             g.DrawString(str, new Font("宋体", 9), new SolidBrush(_pinColor), new PointF(cer, (float)(cer + cer * 0.4)), strFormat);
    230         }
  • 相关阅读:
    Key-Value Memory Network
    Deep Mask Memory Network with Semantic Dependency and Context Moment for Aspect Level Sentiment Clas
    Deep Memory Network在Aspect Based Sentiment方向上的应用
    Deep Memory Network 深度记忆网络
    Self Attention 自注意力机制
    Attention基本公式及其变种
    *端策略优化算法(PPO)
    Policy Gradient 算法
    一本通 农场派对
    A
  • 原文地址:https://www.cnblogs.com/twzy/p/4922976.html
Copyright © 2011-2022 走看看