wpf canvas折线图和点图

前台xaml代码

<Window x:Class="SeaTiger8SimulateEnv.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SeaTiger8SimulateEnv"
        mc:Ignorable="d"
        Title="MainWindow" Height="800" Width="1200">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="400"/>
            <RowDefinition Height="400"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="400"/>
            <ColumnDefinition Width="400"/>
            <ColumnDefinition Width="400"/>
        </Grid.ColumnDefinitions>
        <Canvas Name="can" Margin="5">
        </Canvas>
    </Grid>
</Window>

后台cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Threading;

namespace SeaTiger8SimulateEnv
{
    public partial class MainWindow : Window
    {
        private DispatcherTimer dispatcherTimer = null;
        private int i = 0;
        public Line myLine = new Line();
        public Path myPath = new Path();
        public PathGeometry pg = new PathGeometry();
        public static double intervalX = 50;
        public static double intervalY = 50;
        public static int num = 6;
        public static int scalelHeight = 10;
        //原点 O=(40,350)
        public static int originX = 40;
        public static int originY = 350;
        public static double textXInterval = 2000;
        public static double textYInterval = 1000;
        public static double r2cConvertX ,r2cConvertY;

        public MainWindow()
        {
            InitializeComponent();
            
            dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += new EventHandler(TimeCycle);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
            dispatcherTimer.Start();
        }
        private void TimeCycle(object sender, EventArgs e)
        {
            //清空画布
            can.Children.Clear();
            //画坐标轴
            DrawScale();

            //生成画图用的XY 数据
            double[] dataX = new double[] { 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000 };
            double[] dataY = new double[8];
            for (int i = 0; i < dataY.Length ; i++)
            {
                Random rPoint = new Random();
                var a = rPoint.Next(1000, 6000);
                dataY[i] = a;
                Thread.Sleep(10);
            }
            //数据真实值转成canvas上的位置
            var dataX_can = DataConvert(dataX, "X");
            var dataY_can = DataConvert(dataY, "Y");

            //画折线用的点集
            PointCollection coordinatePoints = new PointCollection();
            //画点
            for (int i = 0; i < dataX.Length; i++)
            {
                Ellipse dataEllipse = new Ellipse();
                dataEllipse.Fill = new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0xff));
                dataEllipse.Width = 4;
                dataEllipse.Height = 4;

                Canvas.SetLeft(dataEllipse, dataX_can[i] - dataEllipse.Width / 2);//-4是为了补偿圆点的大小,到精确的位置
                Canvas.SetTop(dataEllipse, dataY_can[i] - dataEllipse.Height / 2);

                this.can.Children.Add(dataEllipse);

                System.Windows.Point linePoint = new System.Windows.Point((int)dataX_can[i], (int)dataY_can[i]);
                coordinatePoints.Add(linePoint);
            }
            Polyline curvePolyline = new Polyline();
            curvePolyline.Stroke = Brushes.Green;
            curvePolyline.StrokeThickness = 2;

            curvePolyline.Points = coordinatePoints;
            this.can.Children.Add(curvePolyline);
        }
        private void DrawScale()
        {
            Line xAxis = new Line();
            xAxis.X1 = 40;
            xAxis.Y1 = 350;
            xAxis.X2 = 350;
            xAxis.Y2 = 350;
            xAxis.Stroke = new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0));
            xAxis.StrokeThickness = 3;
            xAxis.StrokeStartLineCap = PenLineCap.Round;
            this.can.Children.Add(xAxis);
            Line yAxis = new Line();
            yAxis.X1 = 40;
            yAxis.Y1 = 350;
            yAxis.X2 = 40;
            yAxis.Y2 = 40;
            yAxis.Stroke = new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0));
            yAxis.StrokeThickness = 3;
            yAxis.StrokeStartLineCap = PenLineCap.Round;
            this.can.Children.Add(yAxis);

            //画坐标轴的箭头
            Path x_axisArrow = new Path();//x轴箭头
            Path y_axisArrow = new Path();//y轴箭头
            x_axisArrow.Fill = new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0));
            y_axisArrow.Fill = new SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0));
            PathFigure x_axisFigure = new PathFigure();
            x_axisFigure.IsClosed = true;
            x_axisFigure.StartPoint = new Point(350, 346);                          //路径的起点
            x_axisFigure.Segments.Add(new LineSegment(new Point(350, 354), false)); //第2个点
            x_axisFigure.Segments.Add(new LineSegment(new Point(365, 350), false)); //第3个点
            PathFigure y_axisFigure = new PathFigure();
            y_axisFigure.IsClosed = true;
            y_axisFigure.StartPoint = new Point(36, 40);                          //路径的起点
            y_axisFigure.Segments.Add(new LineSegment(new Point(44, 40), false)); //第2个点
            y_axisFigure.Segments.Add(new LineSegment(new Point(40, 25), false)); //第3个点
            PathGeometry x_axisGeometry = new PathGeometry();
            PathGeometry y_axisGeometry = new PathGeometry();
            x_axisGeometry.Figures.Add(x_axisFigure);
            y_axisGeometry.Figures.Add(y_axisFigure); 
            x_axisArrow.Data = x_axisGeometry;
            y_axisArrow.Data = y_axisGeometry;
            this.can.Children.Add(x_axisArrow);
            this.can.Children.Add(y_axisArrow);
            //XOY字母
            TextBlock textBlockX = new TextBlock();
            textBlockX.Text = "X";
            textBlockX.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            textBlockX.FontSize = 20;
            Canvas.SetLeft(textBlockX, 367);
            Canvas.SetTop(textBlockX, 350);
            can.Children.Add(textBlockX);
            TextBlock textBlockY = new TextBlock();
            textBlockY.Text = "Y";
            textBlockY.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            textBlockY.FontSize = 20;
            Canvas.SetLeft(textBlockY, 20);
            Canvas.SetTop(textBlockY, 10);
            can.Children.Add(textBlockY);
            TextBlock textBlock0 = new TextBlock();
            textBlock0.Text = "0";
            textBlock0.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            textBlock0.FontSize = 20;
            Canvas.SetLeft(textBlock0, 20);
            Canvas.SetTop(textBlock0, 350);
            can.Children.Add(textBlock0);

            //画坐标轴的小竖线
            for (int i = 0; i < num+1; i += 1)//作480个刻度,因为当前x轴长 480px,每10px作一个小刻度,还预留了一些小空间
            {
                Line x_scale = new Line();
                x_scale.StrokeEndLineCap = PenLineCap.Triangle;
                x_scale.StrokeThickness = 1;
                x_scale.Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0));

                x_scale.X1 = originX + i * intervalX;   //原点x=40,每10px作1个刻度
                x_scale.X2 = x_scale.X1;    //在x轴上的刻度线,起点和终点相同

                x_scale.Y1 = originY;           //与原点坐标的y=280,相同
                x_scale.Y2 = x_scale.Y1 - scalelHeight;//刻度线长度为4px

                if (i < num+1)//由于y轴短一些,所以在此作出判断,只作25个刻度
                {
                    //作出Y轴的刻度
                    Line y_scale = new Line();
                    y_scale.StrokeEndLineCap = PenLineCap.Triangle;
                    y_scale.StrokeThickness = 1;
                    y_scale.Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0));

                    y_scale.X1 = originX;            //原点x=40,在y轴上的刻度线的起点与原点相同
                    y_scale.X2 = y_scale.X1 + scalelHeight;//刻度线长度为4px

                    y_scale.Y1 = originY - i * intervalY;  //每10px作一个刻度
                    y_scale.Y2 = y_scale.Y1;    //起点和终点y坐标相同
                    this.can.Children.Add(y_scale);
                }
                this.can.Children.Add(x_scale);
            }
            //画坐标轴下的数字
            for (int i = 1; i < num+1; i++)//7 个标签,一共
            {
                TextBlock x_ScaleLabel = new TextBlock();
                TextBlock y_ScaleLabel = new TextBlock();
               
                x_ScaleLabel.Text = (i * textXInterval).ToString();//只给大刻度添加标签,每50px添加一个标签
                
                Canvas.SetLeft(x_ScaleLabel, originX + intervalX * i - 15);//40是原点的坐标,-12是为了让标签看的位置剧中一点
                Canvas.SetTop(x_ScaleLabel, originY + 2);//让标签字往下移一点
                
                y_ScaleLabel.Text = (i * textYInterval).ToString();
                Canvas.SetLeft(y_ScaleLabel, originX - 40);              //-25px是字体大小的偏移
                Canvas.SetTop(y_ScaleLabel, originY - intervalY * i - 8);  //280px是原点的坐标,同样-6是为了让标签不要上坐标轴叠上
                
                this.can.Children.Add(x_ScaleLabel);
                this.can.Children.Add(y_ScaleLabel);
            }
            //计算实际数字与画布上距离的缩放倍数
            r2cConvertX = intervalX / textXInterval;
            r2cConvertY = intervalX / textYInterval;
        }

        private double[] DataConvert(double[] data, string type)
        {
            double[] canvasData = new double[data.Length];
            if (type == "X")
            {
                for (int i = 0; i < data.Length; i++)
                {
                    canvasData[i] = originX + data[i] * r2cConvertX;
                }
            }
            else
            {
                for (int i = 0; i < data.Length; i++)
                {
                    canvasData[i] = originY - data[i] * r2cConvertY;
                }
            }

            return canvasData;
        }
    }
}

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: WPFCanvas可以用于制作流程,具体流程如下: 1. 首先,在XAML中添加一个Canvas元素,并设置其宽高。 2. 接着,在Canvas中添加Shape元素(如Rectangle、Ellipse等),利用它们来表示流程中的节元素。可以设置它们的颜色、边框等属性,也可以添加鼠标事件等功能。 3. 接下来,需要利用连线元素(如Line、Polyline等)将节元素连接起来,形成整个流程的结构。可以通过设置它们的StartPoint和EndPoint来确定连线的起始和终止位置。 4. 流程中还可以添加文字信息,可以通过TextBlock等元素来实现。 5. 如果需要在节元素和连线元素中添加箭头等标识,可以使用Path元素,根据需要绘制不同形状的箭头标识。 6. 最后,可以将流程中每个元素的位置和属性保存下来,以便后续的编辑和保存操作。 通过以上步骤,可以制作出美观、实用的流程,并且WPFCanvas具有高度可定制性和灵活性,可以满足各种复杂的流程需求。 ### 回答2: WPF Canvas流程是一种基于Windows Presentation Foundation (WPF)技术制作的,用于展示流程或步骤的形化工具。它使用Canvas面板,可以在屏幕上绘制各种形、表、文本等,以帮助用户直观地展示流程、计划、战略和其他复杂信息。 对于WPF Canvas流程,用户可以通过添加形、文本、箭头等元素来创建表。首先,用户需要创建一个Canvas面板,并在其上添加所需的元素。对于不同类型的元素,我们可以使用WPF的各种属性和方法来定义其外观、位置和行为。例如,我们可以使用Shape类(如Rectangle、Ellipse等)来创建各种形状,使用TextBlock类来添加文本,使用Polyline类来绘制折线等。 在WPF Canvas流程中,最常用的元素是箭头。用户可以使用Path类来创建带有箭头标记的连线,以展示不同步骤之间的关系。这些箭头可以定义其颜色、线型、粗细等属性。 此外,WPF Canvas流程还可以使用数据绑定来自动更新表中的元素。用户可以将数据源与Canvas面板的元素绑定,使其自动更新以反映数据的更改。这使得WPF Canvas流程成为一种非常有用的数据可视化工具。 总之,WPF Canvas流程是一种强大的形化工具,可以帮助用户更好地展示复杂的流程和计划。它基于WPF技术,支持各种形、文本、箭头等元素,并且可以使用数据绑定实现自动更新。 ### 回答3: WPF是Windows Presentation Foundation的缩写,是微软推出的一种基于.NET框架的可视化开发技术。在WPF中,Canvas是一种面板控件,它用于布局控件和绘元素。使用Canvas控件,可以方便地绘制流程形化界面。 在绘制流程时,可以先在Canvas上添加基础元素,如矩形、文本框等。然后可以使用WPF提供的属性和方法来调整这些元素的大小、颜色、位置等。此外,Canvas还提供了Transform属性,可以通过设置该属性来实现元素的旋转、缩放等效果。 在绘制流程过程中,可以通过添加事件处理程序来实现元素的交互。比如,可以为元素添加鼠标击事件,当用户单击元素时,可以弹出相应的操作面板。 除了Canvas控件外,WPF还提供了许多其他的控件和功能,如TreeView、ListBox、DataGrid等。这些控件可以用于展示和编辑数据,可以与Canvas控件结合使用,实现更加丰富的形化界面。 总的来说,WPF Canvas控件为流程的绘制提供了便利的工具和方法。开发人员只需要使用C#或VB.NET编写代码,即可实现复杂的形界面。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值