WPF下动态绘制二维的坐标轨迹,采用的linesegment方法。轨迹当选择越来越多多,CPU占有率当选择越来越多高,该如何解决?

WPF中的静态、动态图形绘制问题
桂林老师来信询问数学图形绘制问题。分三种情况说明:
一、利用【工具】中的工具绘制
【工具】中有椭圆、矩形、直线工具,直接使用就行。还有钢笔、铅笔工具(在《WPF和Silverlight教程》中有较详细介绍)。下面的方法均需要编制较多程序。
二、编程绘制静态规则图形&&&
利用Shape基类绘制规则图形
&&& 基类派生了六个实用类,可以实例化直接使用的对象,如 (椭圆)、(直线)、(路径)、(绘制封闭的多边形)、(绘制首尾连接的直线,可以不封闭)和
(矩形),Expression Blend中的图形控件使用了其中的对象。的对象共享以下通用属性:
&&& :说明绘制形状的轮廓颜色;
&&& :说明形状轮廓的粗细;
&&&&:说明如何绘制形状的内部;
还有一些其它属性,这些属性在Blend的【属性】面板中可以找到,不在这里叙述。这些对象控件的使用也很简单,从【工具】面板选择就行,下面只举例说明如何通过编程应用Shape的对象绘制图形。一般在绘制规则图形时会使用到这些类。
要说明的是图形绘制时的坐标体系:
WPF默认的二维坐标原点是设计屏幕的左上角,X正方向向左,Y正方向向下,单位是1英寸(25.4毫米)的1/96。
图3.23.1列举了几个图形绘制方法,界面的根布局类型改为Canvas,按钮事件代码即是图形的绘制程序。
1. 绘制直线
private void button1_Click(object sender,
System.Windows.RoutedEventArgs e)
Line line = new Line();//定义直线对象
&&&&&&&&&&&
line.Stroke = System.Windows.Media.Brushes.R //设置线的颜色,红色
&&&&&&&&&&&
line.X1 = 0; //直线起点
&& &line.Y1 =
0;&&&&&&&&&&&
&&&&&&&&&&&
line.X2 = 150; //直线终点
&&&&&&&&&&&
320;&&&&&&&&&&&
&&&&&&&&&&&
line.StrokeThickness = 5; //直线粗细
&&&&&&&&&&&
this.LayoutRoot.Children.Add(line); //装入界面根布局容器中
图3.23.1 Shape类图形绘制
2. 绘制椭圆
private void button2_Click(object sender,
System.Windows.RoutedEventArgs e)
&&&&&&&&&&&
Ellipse ellipse = new Ellipse();//定义椭圆对象
&&&&&&&&&&&&//属性设置,填充颜色、边粗细、边颜色、宽、高等
&&ellipse.Fill=System.Windows.Media.Brushes.G
&&&&&&&&&&&
ellipse.StrokeThickness =
4;&&&&&&&&&&
&&&&&&&&&&&
ellipse.Stroke =System.Windows.Media.Brushes.G //边,金黄色
&&&&&&&&&&&
ellipse.Width = 80;
&&&&&&&&&&&
ellipse.Height = 200;
&&&&&&&&&&&
//椭圆对象相对于父容器对象Canvas的位置,左边距、上边距
&&Canvas.SetLeft(ellipse,165);
&&&&&&&&&&&
Canvas.SetTop(ellipse,80);
&&&&&&&&&&&
this.LayoutRoot.Children.Add(ellipse);
3. 绘制矩形
private void button3_Click(object sender,
System.Windows.RoutedEventArgs e)
Rectangle rectangle = new Rectangle();//矩形对象
//属性设置,填充颜色、边粗细、边颜色、宽、高等
&&&&&&&&&&&
rectangle.Fill=System.Windows.Media.Brushes.B
&&&&&&&&&&
&rectangle.StrokeThickness =
4;&&&&&&&&&&&&
&&&&&&&&&&
&rectangle.Stroke
=System.Windows.Media.Brushes.P //边,粉色
&&&&&&&&&&&
rectangle.Width = 80;
&&&&&&&&&&
&rectangle.Height = 200;
//矩形对象相对于父容器对象Canvas的位置,左边距、上边距
&&Canvas.SetLeft(rectangle,260);
&&&&&&&&&&&
Canvas.SetTop(rectangle,80);
&&&&&&&&&&&
this.LayoutRoot.Children.Add(rectangle);
4. 封闭多边形
封闭多边形Polygon的绘制需要指明多边形的顶点坐标,只要有了这些点集,Polygon自动依次连接每个顶点,并且自动将最后1个顶点和第1个顶点连接,绘制出封闭多边形,Polygon有个属性Points,需要声明设置此属性的点集合。
private void button4_Click(object sender,
System.Windows.RoutedEventArgs e)
{&&&&&&&&&&&
&& Polygon polygon = new
Polygon();//定义封闭多边形对象
//属性设置,边颜色、填充颜色、边粗细等
&&&&&&&&&&
polygon.Stroke = System.Windows.Media.Brushes.R
//填充,浅海蓝色
&&&&&&&&&&
polygon.Fill = System.Windows.Media.Brushes.LightSeaG
&&polygon.StrokeThickness =
2;&&&&&&&&&&&
&&&&&&&&&&
Point Point1 = new Point(360,80); //封闭多边形的多个顶点坐标
&&&&&&&&&&
Point Point2 = new Point(390,90);
&&&&&&&&&&
Point Point3 = new Point(435,150);
&& Point Point4 = new
Point(390,200);
&& Point Point5 = new
Point(360,300);
&&&&&&&&&&&
//定义点集合对象
&&&&&&&&&&
PointCollection pointCollection = new
PointCollection();&&&&&&&&&&&
&&&&&&&&&&&
pointCollection.Add(Point1); //将顶点添加到点集合对象
&&&&&&&&&&&
pointCollection.Add(Point2);
&&&&&&&&&&&
pointCollection.Add(Point3);
&&pointCollection.Add(Point4);
&&&&&&&&&&&
pointCollection.Add(Point5);&&&&&&&&&&&
&&&&&&&&&&&
polygon.Points = pointC //设置Polygon属性Points的点集合
&&&&&&&&&&&
this.LayoutRoot.Children.Add(polygon);
5. 不封闭形状
&&&&不封闭形状Polyline
的绘制和Polygon的绘制类似,需要指明顶点坐标,只要有了这些点集,Polyline自动依次连接每个顶点,但最后1个顶点和第1个顶点不会连接,从而绘制出不封闭形状,Polyline也有个属性Points,需要声明设置此属性的点集合。
private void button5_Click(object sender,
System.Windows.RoutedEventArgs e)
Polyline polyline = new Polyline();//定义不封闭形状的对象
//属性设置,边颜色、填充颜色、边粗细等
&&&&&&&&polyline.Stroke
= System.Windows.Media.Brushes.R
&&&&&&&&&&&
//填充色,浅海蓝色
&&&&&&&&&&
polyline.Fill =
System.Windows.Media.Brushes.LightSeaG&
&polyline.StrokeThickness = 2;
&&&&&&&&&&
Point Point1 = new Point(460,80); //不封闭形状的多个顶点坐标
&&Point Point2 = new
Point(490,90);
&&&&&&&&&&
Point Point3 = new Point(535,150);
&&&Point Point4
= new Point(490,200);
&&&Point Point5
= new Point(460,300);
&&&&&&&&&&
//定义点集合对象
&&&&&&&&&&
PointCollection pointCollection = new
PointCollection();&
&&&&&&&&&&&&
&&&&pointCollection.Add(Point1);
//将顶点添加到点集合对象
&&&&&&&&&&
pointCollection.Add(Point2);
&&&&&&&&&&
pointCollection.Add(Point3);
pointCollection.Add(Point4);
&&&&&&&&&&
pointCollection.Add(Point5);&&&&&&&&&&&
&&&&&&&&&&
polyline.Points = pointC//Polyline对象属性Points的点集合
&&&&&&&&&&
this.LayoutRoot.Children.Add(polyline);
&&&&&三、编程绘制动态随机图形&
利用Geometry基类绘制动态图形
&&& 类以及派生类可以描绘基本、复杂二维形状的几何图形,可以剪辑图形绘制到屏幕,可以形成动画。的派生类大致可以分为三个类别:基本几何图形、复合几何图形和路径图形。当然,类描绘的图形需要借助其他方法显示。
由于内容较多,这里没有详细介绍类,只是结合自由落体运动轨迹动态图形绘制介绍有关知识。图3.23.2(Example2.23\Window1.xaml)是动态绘制自由落体运动中高度变化的轨迹示例,希望对其他实时图形的绘制有所启发。
图3.23.2左边有个小球,小球(ellipse)被放置在Canvas控件(canvas1)中,从顶端自由下落,在地面弹跳几次后停止,自由落体动画、缓冲曲线设置均使用编程实现。右边是动态绘制的图形,坐标线是直线控件直接放到【设计面板】实现,动态图形点的采集是在定时器的定时处理程序中实现的。右边黑色背景是Canvas控件(canvas2)。运动轨迹的绘制使用几何线段绘制对象PathFigure,此对象有个特点,只要确定绘制的开始点,就会自动连接后面采集的点形成线段,线段需要复合几何图形PathGeometry对象组合形成曲线图形、并借助于Path对象显示。图3.23.2左下方有两个按钮控件,一个用于“启动”(b1,启动自由落体动画),另一个用于“复位”(b2,小球回到开始位置)。最下方有个文本框TextBlock用于显示小球下落过程中高度的数字值,下面是程序。
图3.23.2 实时图形绘制
初始化程序&&
int i=1; //动画时间计数
DispatcherTimer timer=new
DispatcherTimer();//定时器&&&&&&&
PathFigure pf = new PathFigure();//运动轨迹线段绘制
PathGeometry pg = new
PathGeometry();//组合绘制的线段&&&&&&
Path pa = new
Path();//绘制轨迹曲线的容器,用于显示&&&&
DoubleAnimation da=new DoubleAnimation();//小球自由落体运动动画
BounceEase easeBounce=new
BounceEase();//缓动曲线定义&&&&&&
DoubleAnimation rt=new DoubleAnimation();//复位动画
public Window1()
&&&&&&&&&&&
this.InitializeComponent();
&&&&&&&&&&&
pa.Stroke=Brushes.LightG//绘制颜色,亮绿色
&&&&&&&&&&&
pa.StrokeThickness=2;//绘制的线宽
&&&&&&&&&&&
Canvas.SetTop(this.ellipse,0);&
//设置小球起点&&&&&
&&&&&&&&&&&
startpoint();//确定绘制的开始点,自定义程序
&&&&&&&&&&&
timer.Interval=TimeSpan.FromMilliseconds(10);//定时10毫秒
&&&&&&&&&&&
timer.Tick+=new System.EventHandler(timer_Tick); //定时事件
&&&&&&&&&&&
da.Completed+=new System.EventHandler(da_Completed);//动画完成事件
绘制起点自定义程序
private void startpoint()
{&&&&&&&&&&&
&&&&&&&&&&&
pf.StartPoint = new Point(0,0);//定义绘制的第一个点
&&&&&&&&&&&
//加入到PathFigure对象中,true表示描绘线段
&&&&&&&&&&&
pf.Segments.Add(new LineSegment(new
Point(0,0),true));&&&&&&&&&&
&&&&&&&&&&&
pg.Figures.Add(pf); //组合绘制的线段,只要操作一次
&&&&&&&&&&&
pa.Data=//作为Path对象的数据
&&&&&&&&&&&
this.canvas2.Children.Add(pa);//加入Canvas在屏幕显示
&&&&&&&&&&&
Canvas.SetLeft(pa,0);//设置Path对象左边距从0开始,绘制开始的X坐标
&&&&&&&&&&&
Canvas.SetTop(pa,this.canvas2.Height/2);//绘制开始的Y坐标
3. 自由落体动画
private void b1_Click(object sender,
System.Windows.RoutedEventArgs e)
&&&&&&&&&&&
easeBounce.EasingMode=EasingMode.EaseO//缓动曲线模式
&&&&&&&&&&&
da.EasingFunction=easeB//动画缓动曲线设置
da.Duration=TimeSpan.FromSeconds(5);//动画间隔时间5秒
&&&&&&&&&&&
da.From=0;//从高度0开始,起点
&&&&&&&&&&&
da.To=400;//落地高度400,终点
&&&&&&&&&&&
this.ellipse.RenderTransform=new TranslateTransform();//小球位移变换
&&&&&&&&&&&
timer.Start();//启动定时器
&&&&&&&&&&&
ellipse.BeginAnimation(Canvas.TopProperty,da);//启动动画&&&&&&&&&&&
4. 动画完成
private void da_Completed(object sender,
System.EventArgs e)
&&&&&&&&&&&
timer.Stop();&&&&&&
5. 定时器定时事件
private void timer_Tick(object sender,
System.EventArgs e)
&&&&&&&&&&&
double y=Canvas.GetTop(this.ellipse);//获取当前高度
&&&&&&&&&&&
pf.Segments.Add(new LineSegment(new Point(i,y/2),true));//加入
&&&&&&&&&&&
i++;//计数
&&&&&&&&&&&
this.tb.Text=y.ToString();//显示数字值
6. 复位动画程序
private void b2_Click(object sender,
System.Windows.RoutedEventArgs e)
&&&&&&&&&&&
rt.Duration=TimeSpan.FromSeconds(1);//动画时间1秒
&&&&&&&&&&&
rt.From=400;//开始点
&&&&&&&&&&&
rt.To=0;//终点
&&&&&&&&&&&
this.ellipse.RenderTransform=new TranslateTransform();
&&&&&&&&&&&
ellipse.BeginAnimation(Canvas.TopProperty,rt);
&&&&&&&&&&&
pf.Segments.Clear();//PathFigure对象清0,所有绘制线段消失
&&&&&&&&&&&
i=1;//重新计数&
以上的编程对初学者有点困难,其实可以寻找其他可以容易画图的软件生成EXE文件,在WPF中连接就相对简单了。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。君,已阅读到文档的结尾了呢~~
一种基于网格均匀化的刀位轨迹优化方法及其实现
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
一种基于网格均匀化的刀位轨迹优化方法及其实现
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口WPF下动态绘制二维的坐标轨迹,采用的linesegment方法。轨迹越来越多,CPU占有率越来越高,该如何解决?-中国学网-中国IT综合门户网站-提供健康,养生,留学,移民,创业,汽车等信息
> 信息中心 >
WPF下动态绘制二维的坐标轨迹,采用的linesegment方法。轨迹越来越多,CPU占有率越来越高,该如何解决?
来源:互联网 发表时间: 17:59:50 责任编辑:李志喜字体:
为了帮助网友解决“WPF下动态绘制二维的坐标轨迹,采用的linesegment方法。轨迹越来越多,CPU占有率越来越高,该如何解决?”相关的问题,中国学网通过互联网对“WPF下动态绘制二维的坐标轨迹,采用的linesegment方法。轨迹越来越多,CPU占有率越来越高,该如何解决?”相关的解决方案进行了整理,用户详细问题包括:RT,我想知道:WPF下动态绘制二维的坐标轨迹,采用的linesegment方法。轨迹越来越多,CPU占有率越来越高,该如何解决?,具体解决方案如下:解决方案1:
只显示一定时间内的内容就可以了,你看到过任务管理器里面的CPU使用率会24小时全显示的这不废话么。并且,为什么用直线,为什么不用贝赛尔曲线
提问者评价
相关文章:
最新添加资讯
24小时热门资讯
Copyright © 2004- All Rights Reserved. 中国学网 版权所有
京ICP备号-1 京公网安备02号首先来一发图
绘制XY的坐标主要是利用Canvas setLeft和setBottom功能(Canvas内置坐标的功能)
1.首先WPF中的坐标系都是从左到右,从上到下的 即左上角位置(0,0)点,所以XY的Canvas要以(RenderTransformOrigin="0,0",为中心点)进行270&旋转,然后平移&TranslateTransform Y="{Binding ActualHeight,ElementName=canvasInPath}"/&
就是如上所图的XY坐标(绿色的)Line
不旋转的图如下:
&Canvas x:Name="canvasInPath"
RenderTransformOrigin="0,0"&
&Canvas.RenderTransform&
&TransformGroup&
&ScaleTransform/&
&SkewTransform/&
&RotateTransform Angle="270"/&
&TranslateTransform Y="{Binding ActualHeight,ElementName=canvasInPath}"/&
&/TransformGroup&
&/Canvas.RenderTransform&
&!--线和点--&
&Canvas x:Name="canvasLinePoint"&&/Canvas&
&Line X1="0" X2="0" Y1="0" Y2="{Binding ActualWidth,ElementName=canvasInPath}" Stroke="Green" StrokeThickness="1"
Width="1" &&/Line&
&Line X1="0" X2="{Binding ActualHeight,ElementName=canvasInPath}" Y1="0" Y2="0" Stroke="Green" StrokeThickness="1"
Height="1" Canvas.Top="0" &&/Line&
2.如果以XY的Canvas要以(RenderTransformOrigin="0.5,0.5",为中心点)旋转,如果Canvas是正方形,那么只需要旋转270可以了,如果是长方形那么就会出现如下图情况:
3.因为Canvas是旋转的,X和Y的网格线就是蓝色的线,就不在旋转的Canvas中进行画线了(注:在旋转后的Canvas再放置控件都要旋转才能正常)
跟Canvas同一个级别放置两个X和Y网格线的Canvas
Line和TextBlock如何画,看上面的测试代码,然后转换成Code,动态绘制出来。
4.如果按照Canvas 100X100的坐标系绘制出来的图像特别密集下图:
所以我对此做了一个原始坐标和实际绘制坐标进行相应的扩大倍数计算,
/// &summary&
/// &/summary&
public double XWidth
return _xW
this.Width =
//预留100的line长度
scaleNumX = (value - xyShorten) / scaleStandard / (xTotal/ scaleStandard);
当前宽度-预留线的长度/基础倍数/(标尺总值/基础倍数),假如当前宽度是x=700,预留100宽度,基础倍数100,x标尺总刻度是200
那么计算出的scaleNumX=(700-100)/100/(200/100)=3
同理计算出&scaleNumY=(500-100)/100/(100/100)=4 &(y=500 预留100 基础倍数100 y标尺总刻度是100)
原始坐标 (20,90)=&真实绘制坐标(60,360) x*scaleNumX,y*scaleNumY 下图:
完整的xaml代码如下:
&UserControl x:Class="CoordinateXY.UserControlXY"
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="/expression/blend/2008"
xmlns:local="clr-namespace:CoordinateXY"
mc:Ignorable="d"
x:Name="ucontrol"
d:DesignHeight="600" d:DesignWidth="600"&
&Grid Background="Wheat"&
&Canvas x:Name="canvasInPath"
RenderTransformOrigin="0,0"&
&Canvas.RenderTransform&
&TransformGroup&
&ScaleTransform/&
&SkewTransform/&
&RotateTransform Angle="270"/&
&TranslateTransform Y="{Binding ActualHeight,ElementName=canvasInPath}"/&
&/TransformGroup&
&/Canvas.RenderTransform&
&!--线和点--&
&Canvas x:Name="canvasLinePoint"&&/Canvas&
&Line X1="0" X2="0" Y1="0" Y2="{Binding ActualWidth,ElementName=canvasInPath}" Stroke="Green" StrokeThickness="1"
Width="1" &&/Line&
&Line X1="0" X2="{Binding ActualHeight,ElementName=canvasInPath}" Y1="0" Y2="0" Stroke="Green" StrokeThickness="1"
Height="1" Canvas.Top="0" &&/Line&
&!--X坐标尺度--&
&Canvas x:Name="canvasXRuler"
Visibility="Visible" Panel.ZIndex="-1"&
&!--以下为测试代码--&
&Line X1="0" X2="0" Y1="0" Y2="260" Stroke="Blue" StrokeThickness="1" Canvas.Bottom="-8"
Canvas.Left="40"&&/Line&
&TextBlock Text="12" RenderTransformOrigin="0,0" Canvas.Bottom="-25"
Canvas.Left="32"&
&/TextBlock&
&Line X1="0" X2="0" Y1="0" Y2="260" Stroke="Blue" StrokeThickness="1"
Canvas.Bottom="-8"
Canvas.Left="50"&&/Line&
&TextBlock Text="45" RenderTransformOrigin="0,0" Canvas.Bottom="-25"
Canvas.Left="42"&
&/TextBlock&
&Ellipse Width="2" Height="2" Canvas.Left="49" Canvas.Top="49" Stroke="Red" StrokeThickness="1"&&/Ellipse&
&!--Y坐标尺度--&
&Canvas x:Name="canvasYRuler" Panel.ZIndex="-1"&
&!--以下为测试代码--&
&Line X1="0" X2="260" Y1="0" Y2="0" Stroke="Blue" StrokeThickness="1" Canvas.Bottom="10"
Canvas.Left="-8"&&/Line&
&TextBlock Text="Y2" RenderTransformOrigin="0,0" Canvas.Bottom="2"
Canvas.Left="-25"&
&/TextBlock&
&Line X1="0" X2="260" Y1="0" Y2="0" Stroke="Blue" StrokeThickness="1" Canvas.Bottom="20"
Canvas.Left="-8"&&/Line&
&TextBlock Text="Y1" RenderTransformOrigin="0,0" Canvas.Bottom="12"
Canvas.Left="-25"&
&/TextBlock&
&/UserControl&
完整的Code代码如下:
using System.Collections.G
using System.L
using System.T
using System.W
using System.Windows.C
using System.Windows.D
using System.Windows.D
using System.Windows.I
using System.Windows.M
using System.Windows.Media.I
using System.Windows.N
using System.Windows.S
namespace CoordinateXY
/// &summary&
/// UserControlXY.xaml 的交互逻辑
/// &/summary&
public partial class UserControlXY : UserControl
public UserControlXY()
InitializeComponent();
this.Loaded += UserControlXY_L
private void UserControlXY_Loaded(object sender, RoutedEventArgs e)
InitXRuler();
InitYRuler();
#region 变量
/// &summary&
/// 放大倍数 防止坐标尺子重叠
/// &/summary&
private static double scaleNumX = 0;
/// &summary&
/// 放大倍数 防止坐标尺子重叠
/// &/summary&
private static double scaleNumY = 0;
/// &summary&
/// 按照宽度和高度计算放大倍数
/// &/summary&
private double scaleStandard = 50;
/// &summary&
/// x坐标尺度
/// &/summary&
private double xTotal = 150;
/// &summary&
/// Y坐标尺度
/// &/summary&
private double yTotal = 300;
/// &summary&
刻度间隔 10刻度显示一个网格线
/// &/summary&
private double scaleInterval = 10;
/// &summary&
/// 网格刻度线延长出来的长度值
/// 修改此长度看效果图
/// &/summary&
private int xyLine = 0;
/// &summary&
/// xy坐标线长比网格绘制长度长多少
/// &/summary&
private int xyShorten = 50;
/// &summary&
/// 文本距离xy坐标线的位置
/// &/summary&
private int txtDis = 20;
/// &summary&
/// &/summary&
private double _xW
/// &summary&
/// &/summary&
private double _yH
/// &summary&
/// &/summary&
public double YHeight
return _yH
_yHeight =
this.Height =
//预留100的line长度
scaleNumY = (value - xyShorten) / scaleStandard / (yTotal / scaleStandard);
/// &summary&
/// &/summary&
public double XWidth
return _xW
this.Width =
//预留100的line长度
scaleNumX = (value - xyShorten) / scaleStandard / (xTotal / scaleStandard);
#endregion
#region 方法
/// &summary&
/// 初始化X坐标尺
/// &/summary&
private void InitXRuler()
canvasXRuler.Children.Clear();
var xtotal = xTotal + 1;
for (int i = 1; i & i++)
if (i % scaleInterval != 0 && i + 1 != xtotal)
Line xLine = new Line();
xLine.X1 = 1;
xLine.X2 = 0;
xLine.Y1 = 0;
xLine.Y2 = this.Height - xyShorten + xyL//柱状线图形高度;
xLine.Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 255));//蓝色
xLine.StrokeThickness = 1;
xLine.IsHitTestVisible = false;
Canvas.SetLeft(xLine, i * scaleNumX);
Canvas.SetBottom(xLine, -xyLine);//延迟8长度刻度
TextBlock txtBlock = new TextBlock();
txtBlock.Text = (i).ToString();//文本内容
var typeface = new Typeface(txtBlock.FontFamily, txtBlock.FontStyle, txtBlock.FontWeight, txtBlock.FontStretch);
var width = Commons.Helper.TrimmingHelper.GetControlWidth(txtBlock.Text, typeface, txtBlock.FontSize);
Canvas.SetLeft(txtBlock, i * scaleNumX - width / 2);//计算文本宽度 使text内容center居中
Canvas.SetBottom(txtBlock, -txtDis);//刻度下方文本
canvasXRuler.Children.Add(xLine);
canvasXRuler.Children.Add(txtBlock);
/// &summary&
/// 初始化Y坐标尺
/// &/summary&
private void InitYRuler()
canvasYRuler.Children.Clear();
var ytotal = yTotal + 1;
for (int i = 1; i & i++)
if (i % scaleInterval != 0 && i + 1 != ytotal)
Line yLine = new Line();
yLine.X1 = 1;
yLine.X2 = this.Width - xyShorten + xyL//柱状线图形长度;
yLine.Y1 = 0;
yLine.Y2 = 0;
yLine.Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 255));//蓝色
yLine.StrokeThickness = 1;
yLine.IsHitTestVisible = false;
Canvas.SetLeft(yLine, -xyLine);//刻度值
Canvas.SetBottom(yLine, i * scaleNumY);
TextBlock txtBlock = new TextBlock();
txtBlock.Text = (i).ToString();//文本内容
Canvas.SetRight(txtBlock, this.Width + 8);
Canvas.SetBottom(txtBlock, i * scaleNumY - 8);//高度平移8文本内容上下对齐线
canvasXRuler.Children.Add(yLine);
canvasXRuler.Children.Add(txtBlock);
private static UserControlXY uControlXY;
/// &summary&
/// 创建点的位置
/// &/summary&
/// &param name="point"&&/param&
void InCanvasPoint(Point point)
var temp = CreatePointEllipse();
//temp.ToolTip = point.X / scaleNumX + "," + point.Y / scaleNumY;
temp.ToolTip = point.Y / scaleNumX + "," + point.X / scaleNumY + "
" + "(" + point.Y + "," + point.X + ")";
uControlXY.canvasLinePoint.Children.Add(temp);
Panel.SetZIndex(temp, 100);
Canvas.SetLeft(temp, point.X - temp.Height / 2);
Canvas.SetTop(temp, point.Y - temp.Width / 2);
/// &summary&
/// 创建Point
/// &/summary&
void CreatePoint(List&Point& itemList)
if (itemList != null && itemList.Count & 0)
for (int i = 0; i & itemList.C i++)
var startPoint = itemList[i];
var tmpPoint = ConvertPoint(startPoint);
InCanvasPoint(tmpPoint);
if (i + 1 == itemList.Count)
var endPoint = itemList[i + 1];
var tmpEndPoint = ConvertPoint(endPoint);
CreateLine(tmpPoint, tmpEndPoint);
/// &summary&
/// 创建连接的直线
/// &/summary&
/// &param name="startPoint"&&/param&
/// &param name="endPoint"&&/param&
void CreateLine(Point startPoint, Point endPoint)
PathGeometry pg = new PathGeometry();//组合绘制的线段
Path pa = new Path();//绘制轨迹曲线的容器,用于显示
pa.Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0));
pa.StrokeThickness = 1;
PathFigure pf = new PathFigure();
pf.StartPoint = startP
LineSegment line = new LineSegment();
line.Point = endP
pf.Segments.Add(line);
pg.Figures.Add(pf);
uControlXY.canvasLinePoint.Children.Add(pa);
/// &summary&
/// 创建弧线
/// &/summary&
void CreateArcLine(Tuple&Point, Point, double& data)
if (data == null)
Point startPoint = ConvertPoint(data.Item1);
Point endPoint = ConvertPoint(data.Item2);
CreateLine(startPoint, endPoint);
PathGeometry pg = new PathGeometry();//组合绘制的线段
Path pa = new Path();//绘制轨迹曲线的容器,用于显示
pa.ToolTip = data.Item1 + "
" + data.Item2;
//pa.Fill = new SolidColorBrush(Color.FromRgb(255, 0, 0));
pa.Stroke = new SolidColorBrush(Color.FromRgb(255, 0, 0));
pa.StrokeThickness = 1;
PathFigure pf = new PathFigure();
pf.StartPoint = startP
ArcSegment line = new ArcSegment();
line.SweepDirection = SweepDirection.C//顺时针弧
line.Point = endP
//半径 正弦定理a/sinA=2r r=a/2sinA 其中a指的是两个城市点之间的距离 角A指a边的对角
double sinA = Math.Sin(Math.PI * data.Item3 / 180.0);
//计算距离 勾股定理
double x = startPoint.X - endPoint.X;
double y = startPoint.Y - endPoint.Y;
double aa = x * x + y *
double l = Math.Sqrt(aa);
double r = l / (sinA * 2);
line.Size = new Size(r, r);
pf.Segments.Add(line);
pg.Figures.Add(pf);
uControlXY.canvasLinePoint.Children.Add(pa);
/// &summary&
/// 把坐标转换为绘画坐标
/// &/summary&
/// &param name="point"&&/param&
/// &returns&&/returns&
Point ConvertPoint(Point point)
var tmpPoint = new Point();
tmpPoint.X = point.Y * scaleNumY;
tmpPoint.Y = point.X * scaleNumX;
return tmpP
/// &summary&
/// 创建圆点
/// &/summary&
/// &returns&&/returns&
Ellipse CreatePointEllipse()
Ellipse ell = new Ellipse();
ell.Stroke = new SolidColorBrush(Color.FromRgb(255, 0, 0));
ell.Fill = new SolidColorBrush(Color.FromRgb(255, 0, 0));
ell.Height = 8;
ell.Width = 8;
public void Refresh(List&Point& _itemsSource)
canvasLinePoint.Children.Clear();
CreatePoint(_itemsSource);
InitXRuler();
InitYRuler();
public void ClearLine()
this.canvasLinePoint.Children.Clear();
#endregion
#region Customer DependencyObject
/// &summary&
/// 求两点之间的弧线
/// item1 开始坐标 item2 结束坐标 item3 弧度值
/// &/summary&
public Tuple&Point, Point, double& PointArc
get { return (Tuple&Point, Point, double&)GetValue(PointArcProperty); }
set { SetValue(PointArcProperty, value); }
public List&Point& ItemsSource
get { return (List&Point&)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
// Using a DependencyProperty as the backing store for ItemsSource.
This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(List&Point&), typeof(UserControlXY), new PropertyMetadata(null, new PropertyChangedCallback(OnItemsSourceChangedCallback)));
public static void OnItemsSourceChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
if (e.NewValue != null)
uControlXY = d as UserControlXY;
uControlXY.CreatePoint(e.NewValue as List&Point&);
// Using a DependencyProperty as the backing store for PointArc.
This enables animation, styling, binding, etc...
public static readonly DependencyProperty PointArcProperty =
DependencyProperty.Register("PointArc", typeof(Tuple&Point, Point, double&), typeof(UserControlXY), new PropertyMetadata(null, new PropertyChangedCallback(OnPointArcChangedCallback)));
public static void OnPointArcChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
if (e.NewValue != null)
uControlXY = d as UserControlXY;
uControlXY.CreateArcLine(e.NewValue as Tuple&Point, Point, double&);
#endregion
/***********************************************************************
* Copyright(c)
* CLR 版本: 4.0.
* 文 件 名:TrimmingHelper
* 创 建 人:ligl
* 创建日期: 21:05:16
* 修 改 人:ligl
* 修改日期:
* 备注描述:
************************************************************************/
using System.Collections.G
using ponentM
using System.L
using System.T
using System.Windows.M
namespace Commons.Helper
/// &summary&
/// 计算长度是否超出文本宽度的帮助类
/// &/summary&
public class TrimmingHelper
/// &summary&
/// &/summary&
/// &param name="source"&原始文本&/param&
/// &param name="suffix"&省略文本符号&/param&
/// &param name="endNoTrimSource"&追加省略号后面的文本,source+endNoTrimSource总体长度计算省略号&/param&
/// &param name="width"&文本长度&/param&
/// &param name="face"&字体类&/param&
/// &param name="fontsize"&字体大小&/param&
/// &param name="ShowTip"&True标示截取了文本&/param&
/// &returns&&/returns&
public static string Trim(string source, string suffix, string endNoTrimSource, double width, Typeface face, double fontsize, ref bool ShowTip)
if (face != null)
//real display max width.
double realWidth =
//try to get GlyphTypeface.
GlyphTypeface glyphT
face.TryGetGlyphTypeface(out glyphTypeface);
if (glyphTypeface != null)
//calculate end string 's display width.
if (!string.IsNullOrEmpty(endNoTrimSource))
double notrimWidth = 0;
foreach (char c in endNoTrimSource)
glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
notrimWidth += glyphTypeface.AdvanceWidths[w] *
realWidth = width - notrimW
//calculate source 's screen width
double sourceWidth = 0;
if (!string.IsNullOrEmpty(source))
foreach (char c in source)
glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
sourceWidth += glyphTypeface.AdvanceWidths[w] *
//don't need to trim.
if (sourceWidth &= realWidth) return source + endNoTrimS
//calculate suffix's display width
double suffixWidth = 0;
if (!string.IsNullOrEmpty(suffix))
foreach (char c in suffix)
glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
suffixWidth += glyphTypeface.AdvanceWidths[w] *
realWidth = realWidth - suffixW
if (realWidth & 0)
sourceWidth = 0;
string trimStr = string.E
foreach (char c in source)
glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
double cWidth = glyphTypeface.AdvanceWidths[w] *
if ((sourceWidth + cWidth) & realWidth)
ShowTip = true;
return trimStr + suffix + endNoTrimS
trimStr +=
sourceWidth += cW
ShowTip = true;
if (width & suffixWidth) return
else return "...";
ShowTip = false;
return source + endNoTrimS
/// &summary&
/// 获取文本内容宽度的方法
/// &/summary&
/// &param name="source"&&/param&
/// &param name="face"&&/param&
/// &param name="fontsize"&&/param&
/// &returns&&/returns&
public static double GetControlWidth(string source, Typeface face, double fontsize)
double realWidth = 0;
if (face != null)
//try to get GlyphTypeface.
GlyphTypeface glyphT
face.TryGetGlyphTypeface(out glyphTypeface);
if (glyphTypeface != null)
//calculate source 's screen width
if (!string.IsNullOrEmpty(source))
foreach (char c in source)
glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
realWidth += glyphTypeface.AdvanceWidths[w] *
return realW
&使用方式:
&UserControl x:Class="CoordinateXY.UserControlShow"
xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="/expression/blend/2008"
xmlns:local="clr-namespace:CoordinateXY"
mc:Ignorable="d"&
&Grid.RowDefinitions&
&RowDefinition Height="30" /&
&RowDefinition Height="30" /&
&RowDefinition Height="*" /&
&/Grid.RowDefinitions&
&DockPanel VerticalAlignment="Center"&
&TextBox x:Name="txtboxWH" Text="600,600" Width="60"&&/TextBox&
&Button Content="设置宽度和高度" Width="120" Margin="10
0 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Click="BtnRefresh_Click"&&/Button&
&TextBlock Text="开始坐标:" Margin="5 0" VerticalAlignment="Center"&&/TextBlock&
&TextBox x:Name="txtboxArcSpoint" Text="10,10" Width="60" Margin="5 0"&&/TextBox&
&TextBlock Text="结束坐标:" Margin="5 0" VerticalAlignment="Center"&&/TextBlock&
&TextBox x:Name="txtboxArcEpoint" Text="90,90" Width="60" Margin="5 0"&&/TextBox&
&TextBlock Text="弧度值:" Margin="5 0" VerticalAlignment="Center"&&/TextBlock&
&TextBox x:Name="txtboxAngle" Text="80" Width="60" Margin="5 0"&&/TextBox&
&Button Content="设置弧线坐标" Width="120" Margin="5
0 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Click="BtnArc_Click"&&/Button&
&Button Content="Clear所有线" Width="120" Margin="5
0 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Click="BtnClear_Click"&&/Button&
&/DockPanel&
&TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="X Y Demos"
FontSize="20" Grid.Row="1"/&
&Grid Grid.Row="2" Background="DarkOrange"&
&local:UserControlXY
x:Name="uControlXY"
XWidth="600"
YHeight="600" ItemsSource="{Binding XyList,Mode=TwoWay}"
PointArc="{Binding ArcData}" Margin="20"&&/local:UserControlXY&
&/Viewbox&
&/UserControl&
using System.Collections.G
using System.L
using System.T
using System.W
using System.Windows.C
using System.Windows.D
using System.Windows.D
using System.Windows.I
using System.Windows.M
using System.Windows.Media.I
using System.Windows.N
using System.Windows.S
using ponentM
namespace CoordinateXY
/// &summary&
/// UserControlShow.xaml 的交互逻辑
/// &/summary&
public partial class UserControlShow : UserControl
ViewMode vModel = new ViewMode();
public UserControlShow()
InitializeComponent();
this.DataContext = vM
private void BtnRefresh_Click(object sender, RoutedEventArgs e)
//uControlXY.Width = uControlXY.Width * 1.1;
//uControlXY.Height = uControlXY.Height * 1.1;
var txt = txtboxWH.Text.Trim();
string[] whs = txt.Split(',');
if (whs.Length != 2)
double.TryParse(whs[0], out w);
double.TryParse(whs[1], out h);
if (w != 0 && h != 0)
this.uControlXY.XWidth =
this.uControlXY.YHeight =
this.uControlXY.Refresh(vModel.XyList);
private void BtnArc_Click(object sender, RoutedEventArgs e)
var spoints = txtboxArcSpoint.Text.Trim().Split(',');
if (spoints.Length != 2)
Point startPoint = new Point();
double sX;
double sY;
double.TryParse(spoints[0], out sX);
double.TryParse(spoints[1], out sY);
startPoint.X = sX;
startPoint.Y = sY;
var epoints = txtboxArcEpoint.Text.Trim().Split(',');
if (epoints.Length != 2)
Point endPoint = new Point();
double eX;
double eY;
double.TryParse(epoints[0], out eX);
double.TryParse(epoints[1], out eY);
endPoint.X = eX;
endPoint.Y = eY;
var angletxt = txtboxAngle.Text.Trim();
double.TryParse(angletxt, out angle);
vModel.ArcData = new Tuple&Point, Point, double&(startPoint, endPoint, angle);
private void BtnClear_Click(object sender, RoutedEventArgs e)
uControlXY.ClearLine();
public class ViewMode : INotifyPropertyChanged
public ViewMode()
_xyList = new List&Point&();
XyList.Add(new Point(10, 10));
XyList.Add(new Point(40, 50));
XyList.Add(new Point(30, 40));
XyList.Add(new Point(90, 10));
XyList.Add(new Point(20, 90));
XyList.Add(new Point(45.5, 73.2));
XyList.Add(new Point(140, 235));
_arcData = new Tuple&Point, Point, double&(new Point(50, 50), new Point(80, 90), 60);
private Tuple&Point, Point, double& _arcD
private List&Point& _xyL
public event PropertyChangedEventHandler PropertyC
public void OnPropertyChanged(PropertyChangedEventArgs e)
if (PropertyChanged != null)
PropertyChanged(this, e);
public List&Point& XyList
return _xyL
OnPropertyChanged(new PropertyChangedEventArgs("XyList"));
/// &summary&
/// 弧线构成数据
/// &/summary&
public Tuple&Point, Point, double& ArcData
return _arcD
_arcData =
OnPropertyChanged(new PropertyChangedEventArgs("ArcData"));
阅读(...) 评论()

我要回帖

更多关于 当选择越来越多 的文章

 

随机推荐