본문 바로가기
Study/C#

C# Windows Forms 강의 89편: 그래프 그리기 애플리케이션 제작 - 실시간 데이터 시각화

by wawManager 2025. 5. 3.

 

1. 강의 개요

이번 강의에서는 실시간 데이터를 그래프로 시각화하는 애플리케이션을 제작합니다.
Windows Forms의 Chart 컨트롤을 활용하여
시간에 따라 변화하는 데이터를 그래프로 나타내는 기능을 구현합니다.
이 강의에서는 센서 데이터, 주식 가격, CPU 사용량과 같은 데이터를
실시간으로 업데이트하고 시각화하는 방법을 배웁니다.


2. 학습 목표

  • Chart 컨트롤을 사용하여 데이터 시각화
  • 실시간 데이터 업데이트 구현
  • 데이터 시뮬레이션으로 그래프 업데이트 테스트
  • 사용자 친화적인 그래프 UI 제작

3. 기능 요구사항

필수 기능

1️⃣ 그래프 생성 및 시각화:

  • Chart 컨트롤을 사용하여 데이터를 시각화

2️⃣ 실시간 데이터 업데이트:

  • 타이머를 활용하여 일정 간격으로 그래프 데이터 추가

3️⃣ 데이터 리셋 및 저장:

  • 그래프 데이터를 초기화하거나 CSV 파일로 저장

4️⃣ UI 구성 및 동작:

  • 직관적인 그래프 UI와 데이터 관리 버튼 제공

4. 실습: 실시간 데이터 그래프 애플리케이션 제작

1️⃣ 폼 구성

  • 폼(Form) 이름: Form1
  • 컨트롤 배치:

컨트롤 타입 이름 위치 크기

Chart chart 폼 상단 전체 (600 x 400)
Button btnStart 폼 하단 왼쪽 (100 x 30)
Button btnReset 폼 하단 중앙 (100 x 30)
Button btnSave 폼 하단 오른쪽 (100 x 30)

📌 폼 디자인 예시:

--------------------------------------------------
|          [Chart - 실시간 데이터 그래프]        |
--------------------------------------------------
| [Start 버튼] [Reset 버튼] [Save 버튼]          |
--------------------------------------------------

2️⃣ 코드 작성

(1) Chart 초기화

using System;
using System.IO;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace WindowsFormsApp_Graph
{
    public partial class Form1 : Form
    {
        private Timer _timer;
        private Random _random;

        public Form1()
        {
            InitializeComponent();
            InitializeChart();
        }

        // Chart 초기화
        private void InitializeChart()
        {
            chart.Series.Clear();

            // 데이터 시리즈 추가
            var series = new Series("Sensor Data")
            {
                ChartType = SeriesChartType.Line,
                BorderWidth = 2
            };

            chart.Series.Add(series);

            // X축, Y축 설정
            chart.ChartAreas[0].AxisX.Title = "Time (s)";
            chart.ChartAreas[0].AxisY.Title = "Value";
            chart.ChartAreas[0].AxisY.Minimum = 0;
            chart.ChartAreas[0].AxisY.Maximum = 100;

            _random = new Random();
        }
    }
}

(2) 실시간 데이터 업데이트

        // 실시간 데이터 추가
        private void StartUpdatingData()
        {
            _timer = new Timer { Interval = 1000 }; // 1초 간격
            _timer.Tick += (s, e) =>
            {
                var series = chart.Series[0];
                double newValue = _random.Next(0, 100);

                // X축 시간 값 계산
                double time = series.Points.Count;

                series.Points.AddXY(time, newValue);

                // X축 범위 업데이트
                if (series.Points.Count > 20)
                {
                    chart.ChartAreas[0].AxisX.Minimum = series.Points.Count - 20;
                    chart.ChartAreas[0].AxisX.Maximum = series.Points.Count;
                }
            };
            _timer.Start();
        }

        // 데이터 업데이트 시작
        private void btnStart_Click(object sender, EventArgs e)
        {
            StartUpdatingData();
            btnStart.Enabled = false; // 시작 버튼 비활성화
        }

(3) 데이터 리셋 및 저장

        // 데이터 리셋
        private void btnReset_Click(object sender, EventArgs e)
        {
            chart.Series[0].Points.Clear();
            chart.ChartAreas[0].AxisX.Minimum = 0;
            chart.ChartAreas[0].AxisX.Maximum = 20;

            if (_timer != null)
            {
                _timer.Stop();
                btnStart.Enabled = true; // 시작 버튼 활성화
            }
        }

        // 데이터 저장
        private void btnSave_Click(object sender, EventArgs e)
        {
            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
            {
                saveFileDialog.Filter = "CSV 파일 (*.csv)|*.csv";

                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    using (var writer = new StreamWriter(saveFileDialog.FileName))
                    {
                        var series = chart.Series[0];
                        writer.WriteLine("Time,Value");

                        foreach (var point in series.Points)
                        {
                            writer.WriteLine($"{point.XValue},{point.YValues[0]}");
                        }
                    }

                    MessageBox.Show("데이터가 저장되었습니다.", "완료", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }

(4) Designer 코드

        private void InitializeComponent()
        {
            this.chart = new Chart();
            this.btnStart = new Button();
            this.btnReset = new Button();
            this.btnSave = new Button();

            // Chart 설정
            ChartArea chartArea = new ChartArea();
            this.chart.ChartAreas.Add(chartArea);
            this.chart.Location = new System.Drawing.Point(10, 10);
            this.chart.Size = new System.Drawing.Size(600, 400);

            // Start Button 설정
            this.btnStart.Location = new System.Drawing.Point(10, 420);
            this.btnStart.Size = new System.Drawing.Size(100, 30);
            this.btnStart.Text = "Start";
            this.btnStart.Click += new EventHandler(this.btnStart_Click);

            // Reset Button 설정
            this.btnReset.Location = new System.Drawing.Point(120, 420);
            this.btnReset.Size = new System.Drawing.Size(100, 30);
            this.btnReset.Text = "Reset";
            this.btnReset.Click += new EventHandler(this.btnReset_Click);

            // Save Button 설정
            this.btnSave.Location = new System.Drawing.Point(230, 420);
            this.btnSave.Size = new System.Drawing.Size(100, 30);
            this.btnSave.Text = "Save";
            this.btnSave.Click += new EventHandler(this.btnSave_Click);

            // Form 설정
            this.ClientSize = new System.Drawing.Size(640, 480);
            this.Controls.Add(this.chart);
            this.Controls.Add(this.btnStart);
            this.Controls.Add(this.btnReset);
            this.Controls.Add(this.btnSave);
            this.Text = "실시간 데이터 그래프";
        }

3️⃣ 실행 결과

1️⃣ 실시간 데이터 업데이트

  • "Start" 버튼 클릭 → 1초마다 새로운 데이터가 추가되어 그래프 업데이트

2️⃣ 데이터 리셋

  • "Reset" 버튼 클릭 → 그래프 데이터 초기화

3️⃣ 데이터 저장

  • "Save" 버튼 클릭 → CSV 파일로 그래프 데이터 저장

5. 주요 개념 요약

  • Chart: 데이터 시각화를 위한 기본 제공 컨트롤
  • Series: 그래프에 데이터 포인트를 추가하는 객체
  • Timer: 주기적으로 데이터 추가를 실행
  • SaveFileDialog: 데이터를 저장할 파일을 선택하는 UI

 

📌 #CSharp #WindowsForms #Chart #실시간데이터 #데이터시각화 #Timer