Winform GDI+ 绘图一:绘制2D电池
winform桌面软件开发,在工业控制领域的使用还是很广泛的,打算好好学习一下GDI+绘图。以前都是用别人的轮子,自己也打算封装一些工业控制领域常用的控件。
今天要将的是,利用缓动函数动态绘制电池。
首先在网上搜索了一些常用的缓动函数,并用Animation类做了二次封装。(引用自:http://dsqiu.iteye.com ,感谢)
public enum AnimationType
{
Linear,
EaseIn,
EaseOut,
EaseInOut,
BounceIn,
BounceOut,
QuadEaseOut,
QuadEaseIn,
QuadEaseInOut,
QuadEaseOutIn, //新增40种动画效果
ExpoEaseOut,
ExpoEaseIn,
ExpoEaseInOut,
ExpoEaseOutIn,
CubicEaseOut,
CubicEaseIn,
CubicEaseInOut,
CubicEaseOutIn,
QuartEaseOut,
QuartEaseIn,
QuartEaseInOut,
QuartEaseOutIn,
QuintEaseOut,
QuintEaseIn,
QuintEaseInOut,
QuintEaseOutIn,
CircEaseOut,
CircEaseIn,
CircEaseInOut,
CircEaseOutIn,
SineEaseOut,
SineEaseIn,
SineEaseInOut,
SineEaseOutIn,
ElasticEaseOut,
ElasticEaseIn,
ElasticEaseInOut,
ElasticEaseOutIn,
BounceEaseOut,
BounceEaseIn,
BounceEaseInOut,
BounceEaseOutIn,
BackEaseOut,
BackEaseIn,
BackEaseInOut,
BackEaseOutIn
}
自己二次封装Animation的类,对外公开一个缓动函数值改变的事件,以及动画开始、结束的方法。
封装的逻辑是,调用AnimationStart方法后,会在线程池中加入一个定时生产缓动函数对应值的方法,通过调用对外公开的事件。
外部不停调用AnimationStart方法时,会自动扔弃上一次未完成的定时生产缓动函数值的任务。
public class Animation
{
private AnimationType animationType = AnimationType.EaseInOut;
/// <summary>
/// 设置动画类型
/// </summary>
public AnimationType AnimationType { get => animationType; set => animationType = value; }
/// <summary>
/// 设置动画持续时间
/// </summary>
public int Duration
{
get => duration;
set => duration = value;
} private int duration = 200; private int span = 10; private int version = 0; public event EventHandler<AnimationEventArgs> AnimationComing; public float GetEaseProgress(AnimationType ease_type, float linear_progress)
{
switch (ease_type)
{
case AnimationType.Linear:
return linear_progress;
case AnimationType.BackEaseIn:
return AnimationMethod.BackEaseIn(linear_progress, 0, 1, duration);
case AnimationType.BackEaseInOut:
return AnimationMethod.BackEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.BackEaseOut:
return AnimationMethod.BackEaseOut(linear_progress, 0, 1, duration);
case AnimationType.BackEaseOutIn:
return AnimationMethod.BackEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseIn:
return AnimationMethod.BounceEaseIn(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseInOut:
return AnimationMethod.BounceEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseOut:
return AnimationMethod.BounceEaseOut(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseOutIn:
return AnimationMethod.BounceEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.CircEaseIn:
return AnimationMethod.CircEaseIn(linear_progress, 0, 1, duration);
case AnimationType.CircEaseInOut:
return AnimationMethod.CircEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.CircEaseOut:
return AnimationMethod.CircEaseOut(linear_progress, 0, 1, duration);
case AnimationType.CircEaseOutIn:
return AnimationMethod.CircEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseIn:
return AnimationMethod.CubicEaseIn(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseInOut:
return AnimationMethod.CubicEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseOut:
return AnimationMethod.CubicEaseOut(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseOutIn:
return AnimationMethod.CubicEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.ElasticEaseIn:
return AnimationMethod.ElasticEaseIn(linear_progress, 0, 1, duration); case AnimationType.ElasticEaseInOut:
return AnimationMethod.ElasticEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.ElasticEaseOut:
return AnimationMethod.ElasticEaseOut(linear_progress, 0, 1, duration);
case AnimationType.ElasticEaseOutIn:
return AnimationMethod.ElasticEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseIn:
return AnimationMethod.ExpoEaseIn(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseInOut:
return AnimationMethod.ExpoEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseOut:
return AnimationMethod.ExpoEaseOut(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseOutIn:
return AnimationMethod.ExpoEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseIn:
return AnimationMethod.QuadEaseIn(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseInOut:
return AnimationMethod.QuadEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseOut:
return AnimationMethod.QuadEaseOut(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseOutIn:
return AnimationMethod.QuadEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseIn:
return AnimationMethod.QuartEaseIn(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseInOut:
return AnimationMethod.QuartEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseOut:
return AnimationMethod.QuartEaseOut(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseOutIn:
return AnimationMethod.QuartEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseIn:
return AnimationMethod.QuintEaseIn(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseInOut:
return AnimationMethod.QuintEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseOut:
return AnimationMethod.QuintEaseOut(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseOutIn:
return AnimationMethod.QuintEaseOutIn(linear_progress, 0, 1, duration); case AnimationType.SineEaseIn:
return AnimationMethod.SineEaseIn(linear_progress, 0, 1, duration);
case AnimationType.SineEaseInOut:
return AnimationMethod.SineEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.SineEaseOut:
return AnimationMethod.SineEaseOut(linear_progress, 0, 1, duration);
case AnimationType.SineEaseOutIn:
return AnimationMethod.SineEaseOutIn(linear_progress, 0, 1, duration);
default:
return linear_progress;
}
} /// <summary>
/// 动画开始
/// </summary>
public void AnimationStart()
{
int number = Interlocked.Increment(ref version);
ThreadPool.QueueUserWorkItem(Start, number);
}
/// <summary>
/// 动画结束
/// </summary>
public void AnimationStop()
{
Interlocked.Increment(ref version);
} private void Start(object state)
{
try
{
int number = Convert.ToInt32(state);
float timespan = duration / span;
float currentTime = timespan;
while (currentTime < duration)
{
if (number != version)
break;
Thread.Sleep((int)timespan);
AnimationComing.Invoke(this, new AnimationEventArgs() { NowValue = GetEaseProgress(AnimationType, currentTime) });
currentTime += timespan;
if (currentTime >= duration)
{
Thread.Sleep((int)(duration-currentTime));
AnimationComing.Invoke(this, new AnimationEventArgs() { NowValue = GetEaseProgress(AnimationType, currentTime) });
}
} Interlocked.Decrement(ref version);
}
catch
{ }
}
} public class AnimationEventArgs : EventArgs
{
public float NowValue;
}
自绘控件时,只需要注册AnimationComing事件的处理方法,进行控件重绘。如下:
animation.AnimationComing += Animation_AnimationComing; private void Animation_AnimationComing(object sender, AnimationEventArgs e)
{
easeFunctionValue = e.NowValue;
Invalidate();
}
2D电池控件自绘部分就不贴代码,代码已开源,见文章尾部。总体效果如下:

项目开源地址:https://gitee.com/james_happy/IndustryControls
Winform GDI+ 绘图一:绘制2D电池的更多相关文章
- Winform GDI+绘图二:绘制旋转太极图
大家好,今天有时间给大家带来Winform自绘控件的第二部分,也是比较有意思的一个控件:旋转太极图. 大家可以停下思考一下,如果让你来绘制旋转的太极图,大家有什么样的思路呢?我今天跟大家展示一下,我平 ...
- WinForm GDI+ 资料收集
UI(User Interface)编程在整个项目开发过程中是个颇为重要的环节,任何好的解决方案若没有良好的用户界面呈现给最终用户,那么就算包含了最先进的技术也不能算是好程序.UI编程体现在两个方面, ...
- Winform GDI+
什么是GDI+ GDI (Graphics Device Interface), 是属于绘图方面的 API (Application Programming Interface). 因为应用程序不能直 ...
- MFC GDI绘图基础
一.关于GDI的基本概念 什么是GDI? Windows绘图的实质就是利用Windows提供的图形设备接口GDI(Graphics Device Interface)将图形绘制在显示器上. 在Wind ...
- C#-gdi绘图,双缓冲绘图,Paint事件的触发
一. 画面闪烁问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1 绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面 ...
- GDI+ 绘图闪烁解决方法
闲着没事,准备做一个类似于TeeChart的自定义控件,结果第一步的绘图就把我给难倒了,虽然早就知道GDI绘图的闪烁问题很坑,但是却没有想到如此之坑,折腾了两天,才找到解决方法. 首先在窗体加载的时候 ...
- GDI+(一):GDI+ 绘图基础
一.GDI+绘图基础 编写图形程序时需要使用GDI(Graphics Device Interface,图形设备接口),从程序设计的角度看,GDI包括两部分:一部分是GDI对象,另一部分是GDI函数. ...
- Windows GDI绘图基础知识
一.Windows可以画直线.椭圆线(椭圆圆周上的曲线)和贝塞尔曲线.////////////7 个画线函式是:(1)画直线LineTo BOOL LineTo(HDC hdc,int nXEn ...
- WinForm GDI编程:Graphics画布类
命名空间: using System.Drawing;//提供对GDI+基本图形功能的访问 using System.Drawing.Drawing2D;//提供高级的二维和矢量图像功能 using ...
随机推荐
- linux--配置开发环境 --Nginx篇
安装: 安装好了话,我们的nginx的目录在: /etc/nginx 启动: sudo service nginx start 然后访问我们的页面就可以看到了我们的界面 然后我们配置我们的域名: 我 ...
- 都2020年了,这5个java IDE神器你还不知道?
TIOBE的4月份编程语言排行榜出来了,java还是稳坐第一位,java最新的版本也到了13,一直以来java凭借其企业级应用的优势和大量的框架级应用俘获了大量的粉丝和企业客户. 谈到开发者,java ...
- java 之 servlet简介
Servlet 是什么? Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间 ...
- mac OS mysql新建数据库运行sql文件
mysql -uroot -proot123 进入本地数据库 create database 数据库名; use 数据库名; source 文件路径 quit 退出
- Redis数据迁移的三个方法
为什么80%的码农都做不了架构师?>>> 1. rdb数据备份恢复方法 redis 127.0.0.1:6379> SAVE OK 或者 redis-cli -h 127. ...
- BeanDefinition源码解析
我们知道BeanDefintion定义了Bean在IoC容器内的基本数据结构.在学习IoC之前先了解BeanDefition对我们理解IoC容器是有帮助的. 首先BeanDefinition是一个接口 ...
- Nakamori Akina
听过中森明菜的歌以后,一直想写点什么.恰好前段时间看过她的一个访谈https://b23.tv/av13810011,节目里已经39岁左右的她看着已经有些衰老,但是那份属于她的天真却保持的很好. 节目 ...
- 数据库SQL语言从入门到精通--Part 6--单表查询(快来PICK)
数据库从入门到精通合集(超详细,学习数据库必看) 查询操作是SQL语言中很重要的操作,我们今天就来详细的学习一下. 一.数据查询的语句格式 SELECT [ALL|DISTINCT] <目标列表 ...
- 图论--网络流--最大流 HDU 2883 kebab(离散化)
Problem Description Almost everyone likes kebabs nowadays (Here a kebab means pieces of meat grilled ...
- 集训模拟赛-1-T2
好了不要在铺垫了直接整吧就 题目拿来!!!!!!! 倒水 (water) (256MB,1s) [问题描述] 你有一个水桶(记为 0),两个杯子(记为 1,2).水桶中的水量无限,容量也无限.1 号杯 ...