'livecharts'에 해당되는 글 1건

  1. 2026.04.20 [LiveCharts] 설치 및 기본 차트 그리기
반응형

LiveCharts2를 설치하고 간단한 차트를 그려보자.

 

Windows Forms App을 선택한다.

 

Windows Forms App (.NET Framework)를 선택하면 빌드 후 실행 시 에러가 발생한다.

 

 

 

LiveChartsCore.SkiaSharpView.WinForms를 설치한다.

 

Form에 버튼을 하나 배치한다.

 

using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.VisualElements;
using LiveChartsCore.SkiaSharpView.WinForms;
using SkiaSharp;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private bool _isChartDrawn = false;

        public Form1()
        {
            InitializeComponent();

            button1.Click += Button1_Click;
        }

        private void Button1_Click(object? sender, EventArgs e)
        {
            if (_isChartDrawn) return;
            _isChartDrawn = true;

            double[] values1 = new double[] { 2, 1, 3, 5, 3, 4, 6 };
            int[] values2 = new int[] { 4, 2, 5, 2, 4, 5, 3 };

            ISeries[] series = new ISeries[]
            {
                new LineSeries<double>
                {
                    Values = values1,
                    Fill = null,
                    GeometrySize = 20
                },
                new LineSeries<int, StarGeometry>
                {
                    Values = values2,
                    Fill = null,
                    GeometrySize = 20
                }
            };

            DrawnLabelVisual title = new DrawnLabelVisual(
                new LabelGeometry
                {
                    Text = "My chart title",
                    Paint = new SolidColorPaint(SKColor.Parse("#303030")),
                    TextSize = 25,
                    Padding = new LiveChartsCore.Drawing.Padding(15),
                    // padding은 텍스트와 라벨의 경계 사이의 간격을 지정하는 속성이다.
                    // 위 코드에서는 15로 설정되어 있어 텍스트와 라벨의 경계 사이에 15픽셀의 간격이 생긴다.
                    VerticalAlign = LiveChartsCore.Drawing.Align.Start,
                    // vertical align은 Start, Middle, End가 있다. Start는 위쪽, Middle은 가운데, End는 아래쪽에 위치한다.
                    HorizontalAlign = LiveChartsCore.Drawing.Align.Start
                    // horizontal align은 Start, Middle, End가 있다. Start는 왼쪽, Middle은 가운데, End는 오른쪽에 위치한다.
                });

            CartesianChart cartesianChart = new CartesianChart
            {
                Series = series,
                Title = title,
                Location = new System.Drawing.Point(0, 0),
                Size = new System.Drawing.Size(800, 300),
                //Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom
                // 위 코드와 같이 Anchor를 지정하면 폼의 크기가 변경될 때 차트의 크기가 자동으로 조정되는데 그려진 비율이 유지되는게 아니라
                // 그려지지 않은 부분의 사이즈가 그대로 유지되는 방식으로 조정된다.
            };

            Controls.Add(cartesianChart);
        }
    }
}

 

코드를 입력하고 빌드한다.

 

 

버튼을 클릭하면 차트가 표시된다.

 

이번엔 차트에 Zoom & Pan 모드를 설정해 보자.

using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.WinForms;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private bool _isChartAdded = false;

        public Form1()
        {
            InitializeComponent();

            button1.Click += Button1_Click;
        }

        private void Button1_Click(object? sender, EventArgs e)
        {
            if (_isChartAdded) return;
            _isChartAdded = true;

            int[] values = Fetch();
            ISeries[] series = new ISeries[]
            {
                new LineSeries<int>
                {
                    Values = values
                }
            };

            CartesianChart cartesianChart = new CartesianChart
            {
                Series = series,
                ZoomMode = LiveChartsCore.Measure.ZoomAndPanMode.X, // X: Enables zooming and panning on the X axis.
                // 줌 및 팬 모드를 설정하여 X축에서만 작동하도록 지정한다.
                Location = new System.Drawing.Point(0, 0),
                Size = new System.Drawing.Size(800, 300),
                //Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom
            };

            Controls.Add(cartesianChart);
        }

        private static int[] Fetch()
        {
            int[] values = new int[100];
            Random r = new Random();
            int t = 0;

            for (int i = 0; i < 100; i++)
            {
                t += r.Next(-90, 100);
                values[i] = t;
            }

            return values;
        }
    }
}

 

코드를 빌드하고 실행한다.

 

왼쪽 버튼: Pan

오른쪽 버튼: Select

휠: Zoom

 

실시간 업데이트 차트를 만들어 보자.

using LiveChartsCore;
using LiveChartsCore.Defaults;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.WinForms;
using SkiaSharp;
using System.Collections.ObjectModel;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private readonly ObservableCollection<DateTimePoint> _values = new ObservableCollection<DateTimePoint>();
        private readonly object _sync = new object();
        private bool _isReading = true;
        private double[] _separators = Array.Empty<double>();
        private readonly CartesianChart _cartesianChart = new CartesianChart();
        private bool _isChartAdded = false;

        public Form1()
        {
            InitializeComponent();

            button1.Click += Button1_Click;
        }

        private void Button1_Click(object? sender, EventArgs e)
        {
            if (_isChartAdded) return; // 차트가 이미 추가된 경우, 중복 추가 방지
            _isChartAdded = true;

            ISeries[] seriesColection = new ISeries[]
            {
                new LineSeries<DateTimePoint>
                {
                    Values = _values,
                    Fill = null,
                    GeometryFill = null,
                    GeometryStroke = null
                }
            };

            Axis xAxis = new Axis
            {
                Labeler = value => Formatter(new DateTime((long)value)),
                AnimationsSpeed = TimeSpan.FromMilliseconds(0),
                SeparatorsPaint = new SolidColorPaint(SKColors.Gray),
                CustomSeparators = _separators
            };

            _cartesianChart.Series = seriesColection;
            _cartesianChart.XAxes = [xAxis];
            _cartesianChart.Location = new System.Drawing.Point(0, 0);
            _cartesianChart.Size = new System.Drawing.Size(800, 300);
            //_cartesianChart.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;

            Controls.Add(_cartesianChart);
            // 중복 추가를 방지하기 위해 폼 컨트롤에 있는지 아래와 같이 확인할 수도 있다.
            //if (!Controls.Contains(_cartesianChart))
            //    Controls.Add(_cartesianChart);

            _ = ReadData(xAxis);
            // _ = 는 비동기 메서드의 반환값(Task)을 무시하기 위한 구문이다. 반환값은 주로 비동기 작업의 완료를 나타내는
            // Task 객체이지만, 여기서는 반환값을 사용하지 않으므로 _ = 구문을 사용하여 명시적으로 무시한다.
            // 이게 없으면 컴파일러가 반환값이 사용되지 않았다고 경고한다.
        }
        private async Task ReadData(Axis xAxis) // 데이터를 비동기적으로 읽어와 차트에 업데이트하는 메서드
        {
            Random random = new Random();
            while (_isReading)
            {
                await Task.Delay(100);
                lock (_sync)
                {
                    _values.Add(new DateTimePoint(DateTime.Now, random.Next(0, 10)));
                    // DateTimePoint: 날짜와 값을 함께 저장하는 클래스
                    if (_values.Count > 250) _values.RemoveAt(0);
                    _separators = GetSeparators();
                    xAxis.CustomSeparators = _separators;
                }
            }
        }

        private static double[] GetSeparators() // 차트의 X축에 표시할 구분자(시간 간격)를 생성하는 메서드
        {
            DateTime now = DateTime.Now;
            return new double[]
            {
                now.AddSeconds(-25).Ticks,
                now.AddSeconds(-20).Ticks,
                now.AddSeconds(-15).Ticks,
                now.AddSeconds(-10).Ticks,
                now.AddSeconds(-5).Ticks,
                now.Ticks
            };
        }

        private static string Formatter(DateTime date) // X축 레이블을 포맷팅하는 메서드
        {
            double secsAgo = (DateTime.Now - date).TotalSeconds;
            return secsAgo < 1 ? "now" : $"{secsAgo:N0}s ago";
            // "N0"는 소수점 없는 숫자 형식 지정자.
        }
    }
}

 

빌드하고 실행한다.

 

 

Angular Gauge를 만들어 보자.

using LiveChartsCore.Defaults;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Extensions;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.VisualElements;
using LiveChartsCore.SkiaSharpView.WinForms;
using SkiaSharp;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private readonly PieChart pieChart = new PieChart();
        private readonly Random random = new Random();
        private bool _isChartAdded = false;

        public Form1()
        {
            InitializeComponent();

            button1.Click += Button1_Click;
        }

        private void Button1_Click(object? sender, EventArgs e)
        {
            if (_isChartAdded) return; // 차트가 이미 추가된 경우, 중복 추가 방지
            _isChartAdded = true;

            double sectionsOuter = 130; // 섹션의 외부 반경 오프셋
            double sectionsWidth = 20; // 섹션의 최대 반경 너비

            NeedleVisual needle = new NeedleVisual
            {
                Value = 45 // 바늘이 가리키는 값 (pieChart MinValue와 MaxValue 사이)
            };

            pieChart.Series = GaugeGenerator.BuildAngularGaugeSections(
                    new GaugeItem(60, s => SetStyle(sectionsOuter, sectionsWidth, SKColors.LimeGreen, s)), // 첫 번째 섹션: 60% 비율, 녹색
                    new GaugeItem(30, s => SetStyle(sectionsOuter, sectionsWidth, SKColors.Gold, s)),      // 두 번째 섹션: 30% 비율, 노란색
                    new GaugeItem(10, s => SetStyle(sectionsOuter, sectionsWidth, SKColors.Crimson, s)));  // 세 번째 섹션: 10% 비율, 빨간색
            pieChart.VisualElements = [
                new AngularTicksVisual
                {
                    Labeler = value => value.ToString("N1"), // 눈금 레이블 포맷, N1은 소수점 한 자리까지 표시
                    LabelsSize = 16,
                    LabelsOuterOffset = 15,
                    OuterOffset = 65,
                    TicksLength = 20
                },
                needle
                ];
            pieChart.InitialRotation = -225; // 시작 각도 설정
            pieChart.MaxAngle = 270; // 게이지가 차지하는 각도 설정
            pieChart.MinValue = 0; // 게이지의 최소값 설정
            pieChart.MaxValue = 100; // 게이지의 최대값 설정
            pieChart.Location = new System.Drawing.Point(0, 0);
            pieChart.Size = new System.Drawing.Size(400, 400);
            // 바늘(및 차트 전체)의 애니메이션 회전 속도를 늘리거나 줄일 수 있다.
            // 기본값은 약 500밀리초. 아래 설정은 3초(3000밀리초) 동안 부드럽게 회전하도록 한다.
            pieChart.AnimationsSpeed = TimeSpan.FromMilliseconds(3000);
            // 애니메이션의 움직임(Easing) 방식을 지정할 수도 있다.
             pieChart.EasingFunction = LiveChartsCore.EasingFunctions.BounceOut;
            //Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;

            Controls.Add(pieChart);

            Button b1 = new Button
            {
                Text = "Update",
                Location = new System.Drawing.Point(400, 300),
                Size = new System.Drawing.Size(100, 50)
            };
            b1.Click += (sender, e) => needle.Value = random.Next(0, 100);
            Controls.Add(b1);
            b1.BringToFront();
        }

        private static void SetStyle(double sectionsOuter, double sectionsWidth, SKColor color, PieSeries<ObservableValue> series)
        {
            series.OuterRadiusOffset = sectionsOuter; // 섹션의 외부 반경 오프셋 설정
            series.MaxRadialColumnWidth = sectionsWidth; // 섹션의 최대 반경 너비 설정
            series.CornerRadius = 0; // 섹션의 모서리 반경 설정
            series.Fill = new SolidColorPaint(color); // 섹션의 칠하기 색상 설정
        }
    }
}

 

 

※ 참고

Toolbox - LiveChartsCore.SkiaSharpView.WinForms 툴은 사용하지 말자. 그리는 건 되지만 지울 수가 없다.

 

LiveCharts는 코드로만 작성하거나 코드로 UserControl을 만들어 Toolbox에서 사용해야 한다.

 

※ 참고

LiveCharts2 (화면 상단의 Framework를 WinForms 등 원하는 대로 선택해야 한다)

 

반응형
Posted by J-sean
: