如何实现圆形的进度条(ProgressBar)
在我们实际的工作中可能经常使用到圆形的进度条,但是这是怎么实现的呢?其实这只不过是修改了一下ProgressBar的模板,我们在下面的代码中我们将ProgressBar的Value值绑定到Border的Background上面,并且使用了一个ValueToProcessConverter的转换器进行相应地转换,这里重点介绍一下这个转换器
<ProgressBar Name="pb" Minimum="" Maximum="" >
<ProgressBar.Template>
<ControlTemplate TargetType="ProgressBar">
<Border Background="{TemplateBinding Value, Converter={StaticResource ValueToProcessConverter}, ConverterParameter=250}"/>
</ControlTemplate>
</ProgressBar.Template>
</ProgressBar>
下面介绍这部分的源码,并做简要的分析:
首先,获取ProgressBar.Value,然后再获取ConverterParameter=250这个值,通过这两个值就能确定画的圆环的大小和ProgressBar显示的值,然后我们再调用DrawBrush(arg, 100, radius, radius, Thickness)这个函数来进行绘制,具体代码如下:
private Brush DrawBrush(double value, double maxValue, double radiusX, double radiusY, double thickness)
{
DrawingGroup drawingGroup = new DrawingGroup();
DrawingContext drawingContext = drawingGroup.Open();
DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness);
DrawingBrush brush = new DrawingBrush(drawingGroup);
return brush;
}
这里需要注意的是绝不能直接实例化 DrawingContext;但可以通过某些方法(例如 DrawingGroup.Open 和 DrawingVisual.RenderOpen)获取绘图上下文。我们这里是使用DrawingGroup.Open的方法来进行相应的绘图,然后在里面调用里DrawingGeometry这个函数,在这个函数中开始绘制一些DrawEllipse和DrawGeometry,在这个函数中我们讲解一下FormattedText 这个类,使用 FormattedText 对象可以绘制多行文本,且可以单独对该文本中的每个字符设置格式。
private void DrawingGeometry(DrawingContext drawingContext, double value, double maxValue, double radiusX, double radiusY, double thickness)
{
drawingContext.DrawEllipse(null, new Pen(EllipseBrush, thickness), centerPoint, radiusX, radiusY);
drawingContext.DrawGeometry(NormalBrush, new Pen(), GetGeometry(value, maxValue, radiusX, radiusY, thickness)); FormattedText formatWords = new FormattedText(percentString, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, SuccessRateTypeface, SuccessRateFontSize, NormalBrush);
Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2 - SuccessRateFontCorrectionValue);
drawingContext.DrawText(formatWords, startPoint); drawingContext.Close();
}
public class ValueToProcessConverter : IValueConverter
{
readonly double Thickness = 20;
private Point centerPoint;
private double radius;
readonly SolidColorBrush NormalBrush = new SolidColorBrush(Colors.White);
readonly SolidColorBrush EllipseBrush = new SolidColorBrush(Color.FromRgb(107, 132, 165)); string percentString;
private static readonly Typeface SuccessRateTypeface;
private const int SuccessRateFontSize = 65;
readonly double SuccessRateFontCorrectionValue = 12; static ValueToProcessConverter()
{
SuccessRateTypeface = new Typeface(new FontFamily("MSYH"), new FontStyle(), new FontWeight(), new FontStretch());
}
public ValueToProcessConverter()
{ }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is double && !string.IsNullOrEmpty((string)parameter))
{
double arg = (double)value;
double width = double.Parse((string)parameter);
radius = width / 2;
centerPoint = new Point(radius, radius);
return DrawBrush(arg, 100, radius, radius, Thickness);
}
else
{
throw new ArgumentException();
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
} /// <summary>
/// 根据角度获取坐标
/// </summary>
/// <param name="CenterPoint"></param>
/// <param name="r"></param>
/// <param name="angel"></param>
/// <returns></returns>
private Point GetPointByAngel(Point CenterPoint, double r, double angel)
{
Point p = new Point();
p.X = Math.Sin(angel * Math.PI / 180) * r + CenterPoint.X;
p.Y = CenterPoint.Y - Math.Cos(angel * Math.PI / 180) * r;
return p;
} /// <summary>
/// 根据4个坐标画出扇形
/// </summary>
/// <param name="bigFirstPoint"></param>
/// <param name="bigSecondPoint"></param>
/// <param name="smallFirstPoint"></param>
/// <param name="smallSecondPoint"></param>
/// <param name="bigRadius"></param>
/// <param name="smallRadius"></param>
/// <param name="isLargeArc"></param>
/// <returns></returns>
private Geometry DrawingArcGeometry(Point bigFirstPoint, Point bigSecondPoint, Point smallFirstPoint, Point smallSecondPoint, double bigRadius, double smallRadius, bool isLargeArc)
{
PathFigure pathFigure = new PathFigure { IsClosed = true };
pathFigure.StartPoint = bigFirstPoint;
pathFigure.Segments.Add(
new ArcSegment
{
Point = bigSecondPoint,
IsLargeArc = isLargeArc,
Size = new Size(bigRadius, bigRadius),
SweepDirection = SweepDirection.Clockwise
});
pathFigure.Segments.Add(new LineSegment { Point = smallSecondPoint });
pathFigure.Segments.Add(
new ArcSegment
{
Point = smallFirstPoint,
IsLargeArc = isLargeArc,
Size = new Size(smallRadius, smallRadius),
SweepDirection = SweepDirection.Counterclockwise
});
PathGeometry pathGeometry = new PathGeometry();
pathGeometry.Figures.Add(pathFigure); return pathGeometry;
} /// <summary>
/// 根据当前值和最大值获取扇形
/// </summary>
/// <param name="value"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
private Geometry GetGeometry(double value, double maxValue, double radiusX, double radiusY, double thickness)
{
bool isLargeArc = false;
double percent = value / maxValue;
percentString = string.Format("{0}%", Math.Round(percent * 100, 2));
double angel = percent * 360D;
if (angel > 180) isLargeArc = true;
double bigR = radiusX + thickness / 2;
double smallR = radiusX - thickness / 2;
Point firstpoint = GetPointByAngel(centerPoint, bigR, 0);
Point secondpoint = GetPointByAngel(centerPoint, bigR, angel);
Point thirdpoint = GetPointByAngel(centerPoint, smallR, 0);
Point fourpoint = GetPointByAngel(centerPoint, smallR, angel);
return DrawingArcGeometry(firstpoint, secondpoint, thirdpoint, fourpoint, bigR, smallR, isLargeArc);
} /// <summary>
/// 画扇形
/// </summary>
/// <param name="drawingContext"></param>
/// <param name="value"></param>
/// <param name="maxValue"></param>
/// <param name="radiusX"></param>
/// <param name="radiusY"></param>
/// <param name="thickness"></param>
private void DrawingGeometry(DrawingContext drawingContext, double value, double maxValue, double radiusX, double radiusY, double thickness)
{
drawingContext.DrawEllipse(null, new Pen(EllipseBrush, thickness), centerPoint, radiusX, radiusY);
drawingContext.DrawGeometry(NormalBrush, new Pen(), GetGeometry(value, maxValue, radiusX, radiusY, thickness));
FormattedText formatWords = new FormattedText(percentString, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, SuccessRateTypeface, SuccessRateFontSize, NormalBrush);
Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2 - SuccessRateFontCorrectionValue);
drawingContext.DrawText(formatWords, startPoint);
drawingContext.Close();
} /// <summary>
/// 根据当前值和最大值画出进度条
/// </summary>
/// <param name="value"></param>
/// <param name="maxValue"></param>
/// <returns></returns>
private Brush DrawBrush(double value, double maxValue, double radiusX, double radiusY, double thickness)
{
DrawingGroup drawingGroup = new DrawingGroup();
DrawingContext drawingContext = drawingGroup.Open();
DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness);
DrawingBrush brush = new DrawingBrush(drawingGroup);
return brush;
} }
如何实现圆形的进度条(ProgressBar)的更多相关文章
- android圆形进度条ProgressBar颜色设置
花样android Progressbar http://www.eoeandroid.com/thread-1081-1-1.html http://www.cnblogs.com/xirihanl ...
- 详解用CSS3制作圆形滚动进度条动画效果
主 题 今天手把手教大家用CSS3制作圆形滚动进度条动画,想不会都难!那么,到底是什么东东呢?先不急,之前我分享了一个css实现进度条效果的博客<CSS实现进度条和订单进度条>,但是呢, ...
- 进度条ProgressBar
在本节中,作者只写出了进度条的各种样式,包括圆形.条形,还有自定义的条形,我想如果能让条形进度条走满后再继续从零开始,于是我加入了一个条件语句.作者的代码中需要学习的是handler在主线程和子线程中 ...
- WPF 进度条ProgressBar
今天研究了一下wpf的进度条ProgressBar 1.传统ProgressBar WPF进度条ProgressBar 这个控件,如果直接写到循环里,会死掉,界面会卡死,不会有进度.需要把进度条放到单 ...
- Android零基础入门第51节:进度条ProgressBar
原文:Android零基础入门第51节:进度条ProgressBar 不知不觉这已经是第51期了,在前面50期我们学了Android开发中使用频率非常高的一些UI组件,当然这些组件还不足够完成所有AP ...
- css3圆形百分比进度条的实现原理
原文地址:css3圆形百分比进度条的实现原理 今天早上起来在查看jquery插件机制的时候,一不小心点进了css3圆形百分比进度条的相关文章,于是一发不可收拾,开始折腾了... 关于圆形圈的实现,想必 ...
- 在DrawingVisual上绘制圆形的进度条,类似于IOS系统风格。
1.说明:在WPF中,文件下载时需要显示下载进度,由于系统自带的条型进度条比较占用空间,改用圆形的进度条,需要在DrawingVisual上呈现. 运行的效果如图: private Point Get ...
- Android 自学之进度条ProgressBar
进度条(ProgressBar)也是UI界面中的一种非常使用的组件,通常用于向用户显示某个耗时完成的百分比.因此进度条可以动态的显示进度,因此避免长时间地执行某个耗时操作时,让用户感觉程序失去了响应, ...
- WPF的进度条progressbar,运行时间elapse time和等待spinner的实现
今天用.NET 4.5中的TPL的特性做了个小例子,实现了WPF的进度条progressbar,运行时间elapse time和等待spinner. 先上图吧. 这个例子包含4个实现,分别是同步版 ...
随机推荐
- win7重装系统
读了四年大学的计算机专业,说自己不会重装系统真的会笑掉大牙,但人家是女生,怕东怕西的,害怕弄坏自己的电脑,毕竟上计算机课最重要的是电脑,嘿嘿,其实是为了开wifi和看电视剧.今天终于有一台闲置的计算机 ...
- 从Excel表导入数据到Table
步骤: 1.写第一行SQL,(本sql对应的是oracle数据库) ="INSERT INTO TD_PROMOTION_RATE VALUES("&A3&&quo ...
- 乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很 ...
- 2018AVA: A Video Dataset of Spatio-temporally Localized Atomic Visual Actions
论文标题:AVA: A Video Dataset of Spatio-temporally Localized Atomic Visual Actions 来源/作者机构情况: 谷歌,http:// ...
- http/2 多路复用技术
虽然 HTTP 1.1 默认启用长TCP连接,但所有的请求-响应都是按序进行的(这里的长连接可理解成半双工协议.即便是HTTP 1.1引入了管道机制,也是如此).复用同一个TCP连接期间,即便是通过管 ...
- AI Factorization Machine(FM)算法
FM算法 参考链接: https://www.csie.ntu.edu.tw/~b97053/paper/Rendle2010FM.pdf
- <转>浅谈缓存击穿、缓存并发和缓存失效
原文地址:缓存穿透.缓存并发.缓存失效之思路变迁 我们在用缓存的时候,不管是Redis或者Memcached,基本上会通用遇到以下三个问题: 缓存穿透 缓存并发 缓存失效 一.缓存穿透 注 ...
- Omi框架学习之旅 - 之开篇扯蛋
说实话, 我也不知道Omi是干啥的, 只因此框架是alloyTeam出的, dntzhang写的, 也有其他腾讯大神参与了, 还有一些其他贡献者, 以上我也不太清楚, 当我胡说八嘎. 因其写法有人说好 ...
- 7-(基础入门篇)关于STM32底层程序使用说明
https://www.cnblogs.com/yangfengwu/p/9357695.html 基础教程源码链接请在淘宝介绍中下载,由于链接很容易失效,如果失效请联系卖家,谢谢 https://i ...
- [01] 初识SpringBoot:Hello World
引用百科的一句话来说,SpringBoot是一款全新框架,设计目的是为了简化新Spring应用的初始搭建以及开发过程. 怎么讲呢,首先要明确的就是SpringBoot不是替代Spring的一种解决方案 ...