zoukankan      html  css  js  c++  java
  • 模拟Windows任务管理器CPU使用率的动态折线图-农夫山泉

    Delphi的TCanvas类可以实现各种复杂的图形输出功能,基于近期项目的需求,利用它实现了一个很炫的动态折线图(模拟了资源管理器中CPU使用率的折线图),可以直观地展现出数值的实时变化情况。

    这段代码里边有几个核心的地方:

    • 首先是为了缓解刷新时画布闪烁,利用了双缓冲的原理;
    • 其次结合队列,保证了数据的顺序压入;
    • 还有就是一些简单的数组算法。

    最终的效果如下:

    单元代码如下:

    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls,Contnrs;
     
    const
      {* 网格间隔 *}
      GridSpace = 12;
      {* 移动步长(能够被间隔整除) *}
      MoveStep = 3;
      {* Y轴最大值(最大刻度) *}
      MaxY = 100;
     
    type
      TForm1 = class(TForm)
        Timer1: TTimer;
        Button1: TButton;
        Image1: TImage;
        procedure DrawPL(Shower:TImage);
        procedure Timer1Timer(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure FormShow(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
     
    var
      Form1: TForm1;
      {* 网格竖线X坐标数组 *}
      GridXPArr: array of Integer;
      {* 点坐标数组 *}
      PointLst: array of TPoint;
      {* 数值队列 *}
      YPQueue: TQueue;
      {* 数值指针 *}
      PYValue: PInteger;
      {* 网格偏移量 *}
      X: Word;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      YValue:Integer;
    begin
      Randomize;
      YValue := Random(100);
      //新Y坐标点按顺序压入队列
      New(PYValue);
      PYValue^ := YValue;
      YPQueue.Push(PYValue);
    end;
     
    procedure TForm1.DrawPL(Shower:TImage);
    var
      Bit: TBitmap;
      i: Integer;
      PW,PH: Integer;
      YValue:Integer;
    begin
      //偏移量计算
      Inc(X);
      if X = GridSpace div MoveStep then
      X := 0;
      //初始化画布(双缓冲)
      Bit := TBitmap.Create;
      try
        PW := Shower.Width;
        PH := Shower.Height;
        Bit.Width := PW;
        Bit.Height := PH;
        //初始化网格竖线X坐标数组长度为宽/间隔+1
        SetLength(GridXPArr,PW div GridSpace + 1);
        with Bit.Canvas do
        begin
          Brush.Color := clBlack;
          Brush.Style := bsSolid;
          Rectangle(0,0,PW,PH);
          Pen.Color := $00408000;
          //画网格,根据偏移量实现动态效果
          for i := 0 to PW div GridSpace + 1 do
          begin
            GridXPArr[i] := GridSpace * i - X * MoveStep;
            MoveTo(GridXPArr[i],0);
            LineTo(GridXPArr[i],PH);
          end;
          for i := 0 to PH div GridSpace do
          begin
            MoveTo(0,GridSpace * i);
            LineTo(PW,GridSpace * i);
          end;
          //画折线
          Pen.Color := clLime;
          YValue := 0;
          //如果队列中有新的Y坐标点,则输出
          if YPQueue.Count > 0 then
          begin
            PYValue := YPQueue.Pop;
            YValue := PYValue^;
            Dispose(PYValue);
          end;
          //画笔移动到起点位置
          MoveTo(0,PH);
          //每执行一次函数,Y坐标向前移动一位,并连线各个点
          for i := 0 to Length(PointLst) - 2 do
          begin
            PointLst[i].Y := PointLst[i + 1].Y;
            LineTo(PointLst[i+1].X,PointLst[i+1].Y);
          end;
          //按比例更新最后一位坐标点
          PointLst[Length(PointLst)-1].X := PW;
          PointLst[Length(PointLst)-1].Y := PH - (YValue  * PH div MaxY);
          //打印信息(可根据需要调整显示位置和内容)
          Brush.Style:=bsClear;
          Font.Color:=clYellow;
          TextOut(10,10,'数值:'+inttostr(YValue));
        end;
        Shower.Canvas.Draw(0,0,Bit);
      finally
        Bit.Free;
      end;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      i:Integer;
    begin
      YPQueue := TQueue.Create;
      //初始化坐标点个数为宽/步长+1
      SetLength(PointLst,Image1.Width div MoveStep + 1);
      //初始化坐标点为X轴基线位置
      for i := 0 to Length(PointLst) - 1 do
      begin
        PointLst[i].X := i*MoveStep;
        PointLst[i].Y := Image1.Height;
      end;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      YPQueue.Free;
    end;
     
    procedure TForm1.FormShow(Sender: TObject);
    begin
      DrawPL(Image1);
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      DrawPL(Image1);
    end;
     
    end.
  • 相关阅读:
    输入一个1-9的数i,再输入一个数字n,表示 i 出现的次数,输入的2个数字 i 和 n 组合成如下表达式:如i=2,n=4,2+22+222+2222=?,计算结果是多少?
    现有数列1/2;2/3;3/5;5/8······第十次出现的是什么?
    猜数游戏:范围时1-100,若错误就提示大了还是小了,猜对则结束,允许猜10次,游戏结束后对玩家评价:1次猜对;5次内猜对;10次内猜对;没有猜对
    登录模拟,用户名和密码输入错误后给出相关错误提示,并告知还有多少次错误机会,如果5次验证失败将冻结账户
    30人围坐轮流表演节目,按顺序数1-3,每次数到3的人就表演节目,表演过的人不再参加报数,那么在仅剩一个人没有表演的时候,共报数多少人次?
    docker 自定义镜像
    php 镜像richarvey/nginx-php-fpm的ngnix配置
    php tp5常用小知识
    php Tp5下mysql的增删改查
    php 面试常问问题
  • 原文地址:https://www.cnblogs.com/chenmfly/p/4818328.html
Copyright © 2011-2022 走看看