【问题标题】:c# chart to image with LiveChartsc# 使用 LiveCharts 绘制图表
【发布时间】:2017-10-25 12:38:34
【问题描述】:

我有一个小问题。我想将我的图表导出到图像。我知道使用 beto-rodriguez (here) 给出的代码是可能的。

但我有一个问题,我无法通过在屏幕上显示它来获得我可以拥有的东西。见上图。在右下角,我将图像保存在 png 中。在图像的左侧,我有一个图表,所有参数都显示在我想要的位置。

您知道保存的图像中是否可以有相同的图表(在左侧)? 实际上,我使用线程自动捕获(复制/粘贴)图像。

你知道我必须设置哪些参数才能获得正确的图像吗?

Double chart

提前致谢。 问候。

*********************************编辑后

抱歉,我的回复晚了。我试试你说的,但不幸的是我做不到我想要的。 我将解释我的工作: 我有一个类“MakeReport”,它可以调用另一个类“GraphMaker”:

MyGraph = new GraphMaker();
MyGraph = GiveAGraph(MyGraph);

“MakeReport”类将使用子程序“GiveAGraph()”完成带有一些值的图表:

GraphData.SeriesCollection.Add(new RowSeries
   {
       Title = Criteria, 
       Values = DataValues,
       ScalesYAt = Index,
       DataLabels = true
    });

“GiveAGRaph()”结束。

现在我准备好显示一个图表,我想用它来制作图像并用于测试(和调试)我显示它:

// Chart to Image
MyGraph.GiveMeAnImageFromChart();      <-- to make a picture with the chart
// Show the graph
MyGraph.Show();                        <-- for debug and test, i display it.

使用“MyGraph.GiveAnImageFromChart()”,我没有与“MyGraph.Show()”相同的结果。图片(另存为png)与显示的图表不同。

“GraphMaker”类中包含的子程序“GiveAnImageFromChart”是:

public void GiveMeAnImageFromChart()
    {
            var viewbox = new Viewbox();
            myChart.Background = Brushes.White;
            myChart.DataContext = this;

            // myChart  il faut tout mettre en paramètres

            viewbox.Child = myChart;
            viewbox.Measure(myChart.RenderSize);
            viewbox.Arrange(new Rect(new Point(0, 0), myChart.RenderSize));

            myChart.Update(true, true); //force chart redraw
            viewbox.UpdateLayout();

            SaveToPng(myChart, "chart.png");
            //png file was created at the root directory.

    }

“myChart”变量是公开的。使用的“SaveToPng”程序来自您的示例 (here)。

为了保存图片,我尝试了以下方法:

public System.Drawing.Bitmap ControlToImage(Visual target, double dpiX, double dpiY)
    {
        if (target == null)
        {
            return null;
        }
        // render control content
        Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
        Console.WriteLine("Bounds width = " + bounds.Width + " et bounds height = " + bounds.Height);
        RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
                                                        (int)(bounds.Height * dpiY / 96.0),
                                                        dpiX,
                                                        dpiY,
                                                        PixelFormats.Pbgra32);
        DrawingVisual dv = new DrawingVisual();
        using (DrawingContext ctx = dv.RenderOpen())
        {
            VisualBrush vb = new VisualBrush(target);
            ctx.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), bounds.Size));
        }
        rtb.Render(dv);

        //convert image format
        MemoryStream stream = new MemoryStream();
        BitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(rtb));
        encoder.Save(stream);

        return new System.Drawing.Bitmap(stream);
    }

与:

Bitmap ImageChart = MyGraph.ControlToImage(MyGraph, MyGraph.Width, MyGraph.Height);

使用这种方法,我有一个错误,因为“bounds.Width”和“bounds.Height”等于-8。最后,我没有要转换的图表。

我认为我在“ControlImage”中给出了错误的“视觉目标”,我错过了一些东西,但我不知道是什么。如果您需要更多信息,请询问我。 提前感谢您的帮助。

PS:对不起我的英语。不要犹豫,纠正我。

【问题讨论】:

    标签: c# wpf image livecharts


    【解决方案1】:

    感谢 bto-rdz,我提出了解决方案。我发现我没有正确使用 Livecharts。 因此,如果有人需要,我会发布我的代码。

    这是我的 GraphMaker.xaml 文件:

    <UserControl x:Class="MyProject.GraphMaker"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            xmlns:local="clr-namespace:MyProject"
            mc:Ignorable="d" 
            d:DesignHeight="730" d:DesignWidth="1660">
    <Grid>
    </Grid>
    </UserControl>
    

    还有我的 GraphMaker.xaml.cs 文件

        using System;
    using System.IO;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using LiveCharts;
    using LiveCharts.Wpf;
    using System.Collections.Generic;
    using System.ComponentModel;
    
    
    namespace MyProject
    {    
        public partial class GraphMaker : UserControl
        {
            // PUBLIC
            public CartesianChart MyTestChart;
            public SeriesCollection MySeriesCollection { get; set; }
            public string[] Labels { get; set; }
            public string AxisTitle { get; set; }
            public Func<double, string> YFormatter { get; set; }
            public Axis Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, Axis8, Axis9, Axis10, AxisXChart;
    
    
            public GraphMaker()
            {
                InitializeComponent();
                MySeriesCollection = new SeriesCollection();
    
                MyTestChart = new CartesianChart
                {
                    DisableAnimations = true,
                    Width = 1600,
                    Height = 700,
                    Series = MySeriesCollection
                };
    
                MyTestChart.LegendLocation = LegendLocation.Right;
    
                // *** Axis 1 ***
                Axis1 = new Axis();
                Axis1.Foreground = Brushes.DodgerBlue;
                Axis1.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis1.LabelFormatter = YFormatter;
                MyTestChart.AxisY.Add(Axis1);
    
                // *** Axis 2 ***
                Axis2 = new Axis();
                Axis2.Foreground = Brushes.IndianRed;
                Axis2.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis2.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis2);
    
                // *** Axis 3 ***
                Axis3 = new Axis();
                Axis3.Foreground = Brushes.Gold;
                Axis3.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis3.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis3);
    
                // *** Axis 4 ***
                Axis4 = new Axis();
                Axis4.Foreground = Brushes.Gray;
                Axis4.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis4.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis4);
    
                // *** Axis 5 ***
                Axis5 = new Axis();
                Axis5.Foreground = Brushes.DeepSkyBlue;
                Axis5.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis5.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis5);
    
                // *** Axis 6 ***
                Axis6 = new Axis();
                Axis6.Foreground = Brushes.HotPink;
                Axis6.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis6.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis6);
    
                // *** Axis 7 ***
                Axis7 = new Axis();
                Axis7.Foreground = Brushes.Orange;
                Axis7.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis7.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis7);
    
                // *** Axis 8 ***
                Axis8 = new Axis();
                Axis8.Foreground = Brushes.RoyalBlue;
                Axis8.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis8.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis8);
    
                // *** Axis 9 ***
                Axis9 = new Axis();
                Axis9.Foreground = Brushes.Black;
                Axis9.Position = AxisPosition.RightTop;
                Axis9.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis9);
    
                // *** Axis 10 ***
                Axis10 = new Axis();
                Axis10.Foreground = Brushes.DarkTurquoise;
                Axis10.Position = AxisPosition.RightTop;
                YFormatter = value => value.ToString("N2");
                Axis10.LabelFormatter = YFormatter;
                //MyTestChart.AxisY.Add(Axis10);
    
                AxisXChart = new Axis();
                AxisXChart.Title = AxisTitle;
                AxisXChart.Labels = Labels;
            }
    
    
            public void TakeTheChart()
            {
                var viewbox = new Viewbox();
                viewbox.Child = MyTestChart;
                viewbox.Measure(MyTestChart.RenderSize);
                viewbox.Arrange(new Rect(new Point(0, 0), MyTestChart.RenderSize));
                MyTestChart.Update(true, true); //force chart redraw
                viewbox.UpdateLayout();
    
                SaveToPng(MyTestChart, "Chart.png");
                //png file was created at the root directory.
            }
    
            public void SaveToPng(FrameworkElement visual, string fileName)
            {
                var encoder = new PngBitmapEncoder();
                EncodeVisual(visual, fileName, encoder);
            }
    
            private static void EncodeVisual(FrameworkElement visual, string fileName, BitmapEncoder encoder)
            {
                var bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32);
                bitmap.Render(visual);
                var frame = BitmapFrame.Create(bitmap);
                encoder.Frames.Add(frame);
                using (var stream = File.Create(fileName)) encoder.Save(stream);
            }
        }
    }
    

    希望能帮到你。

    祝你有美好的一天。再见。

    【讨论】:

    • +1 感谢您的代码让我开始,但如果 CartesianChart 是 UserControl 的孩子,我只能渲染原始 CartesianChart 并且我得到空白/黑色图像所以我想知道您是如何设法做到的让它工作。 [从具有 LiveChart 的 UserControl 渲染图像](stackoverflow.com/questions/51823020/…)
    • 您好 KMC,您是否尝试为图像添加颜色?我遇到了同样的问题,而且图像似乎没有背景颜色。
    【解决方案2】:

    您指出的示例是在内存中创建了一个新图表实例,这就是您获得不同图像的原因,您可以在两个图表中重现相同的属性,一个呈现在 UI 中,另一个是您在内存中创建,或者您可以在 UI 中打印当前实例,如本期所述:

    https://github.com/beto-rodriguez/Live-Charts/issues/243

    希望对你有帮助

    【讨论】:

    • 如果我没有将 DisableAnimations 设置为 false,那么我会得到空白图表 png(没有 ChartPoint 的图表)这是为什么?
    【解决方案3】:

    我已经编写了扩展方法以将笛卡尔图表中的图像另存为 Windows 窗体。它可以编辑你自己的方式来获得最好的。

            public static bool ChartToImage(this LiveCharts.WinForms.CartesianChart cartesianChart, LineSeries data, Axis AxisX, Axis AxisY,double Width, double Height, string fileName, string targetPath, out string locationOfImage, out Exception returnEx)
        {
    
            bool status = false;
            returnEx = null;
            locationPath = null;
            try
            {
                var myChart = new LiveCharts.Wpf.CartesianChart
                {
                    DisableAnimations = true,
                    Width = Width,
                    Height = Height,
                    Series = new SeriesCollection(cartesianChart.Series.Configuration)
                    {
                       new LineSeries
                       {
                           Title = data.Title,
                           LineSmoothness = data.LineSmoothness,
                           StrokeThickness = data.StrokeThickness,
                           PointGeometrySize = data.PointGeometrySize,
                           Stroke = data.Stroke,
                           Values=data.Values
                       }
                    }
    
                };
                myChart.AxisX.Add(new Axis { IsMerged = AxisX.IsMerged, FontSize = AxisX.FontSize, FontWeight = AxisX.FontWeight, Foreground = AxisX.Foreground, Separator = new LiveCharts.Wpf.Separator { Step = AxisX.Separator.Step, StrokeThickness = AxisX.Separator.StrokeThickness, StrokeDashArray = AxisX.Separator.StrokeDashArray, Stroke = AxisX.Separator.Stroke }, Title = AxisX.Title, MinValue = AxisX.MinValue, MaxValue = AxisX.MaxValue });
                myChart.AxisY.Add(new Axis { IsMerged = AxisY.IsMerged, FontSize = AxisY.FontSize, FontWeight = AxisY.FontWeight, Foreground = AxisY.Foreground, Separator = new LiveCharts.Wpf.Separator { Step = AxisY.Separator.Step, StrokeThickness = AxisY.Separator.StrokeThickness, StrokeDashArray = AxisY.Separator.StrokeDashArray, Stroke = AxisX.Separator.Stroke }, Title = AxisY.Title, MinValue = AxisY.MinValue, MaxValue = AxisY.MaxValue });
    
    
                var viewbox = new Viewbox();
                viewbox.Child = myChart;
                viewbox.Measure(myChart.RenderSize);
                viewbox.Arrange(new Rect(new System.Windows.Point(0, 0), myChart.RenderSize));
                myChart.Update(true, true); //force chart redraw
                viewbox.UpdateLayout();
    
                var encoder = new PngBitmapEncoder();
                var bitmap = new RenderTargetBitmap((int)myChart.ActualWidth, (int)myChart.ActualHeight, 96, 96, PixelFormats.Pbgra32);
                bitmap.Render(myChart);
                var frame = BitmapFrame.Create(bitmap);
                encoder.Frames.Add(frame);
                string path = Path.Combine(targetPath, fileName);
                using (var stream = File.Create(path))
                {
                    encoder.Save(stream);
                    locationPath = path;
                }
                myChart = null;
                viewbox = null;
                encoder = null;
                bitmap = null;
                frame = null;
                status = true;
            }
            catch (Exception ex)
            {
                returnEx = ex;
                status = false;
            }
            return status;
        }
    

    在你的主程序上:

                        if(cartesianChart1.ChartToImage(data,axisX,axisY,600,200,"test.png", locationImage, out string locationOfFile, out Exception returnEx))
                    {
                        System.Windows.Forms.MessageBox.Show(locationOfFile);
                    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      相关资源
      最近更新 更多