본문으로 바로가기

C# Chart 사용법 요약

category 개발언어/C# 2017. 10. 30. 16:56
Chart(Graph)를 표시혹은 사용할때 시간축X에 대한 처리는  정수또는 순서로 나열된 Data를 처리하는 것 보다  매우 까다롭다. 특히나 시간축은 마이크로,밀리,초,분 단위로 처리되기도 하고 분,시간,일,월,분기,년 단위로 평균또는 최대값,산포 등을 계산하기 때문에 단순 Data의 나열을 그래프로 표시하는것과는 차원이 다른 작업량을 필요로 하게 된다. 시간과 관련해서는 소요시간및 경과기간의 계산도 어렵고 사용방법도 잘 기억되지 않는다. 또한 Text로 저장된 파일또는 문서에서 시간 Data로 변환하는 과정도 복잡하다, 이러한 이유 때문에 별도로 메모해 두지 않으면 다음에 다시 작업하기가 거의 불가능할 정도로 기억하기도 어렵다. 매번 작업할 때 마다 기억이 떠오르지 않아 힘들어 하던 기억이 있어서 정리를 해둔다. 여기서는 시간축에관한 처리방법과 C#에서 Chart 사용법을 요약해서 정리한다.

MSCHART_ZOOM.zip

Data 생성및 입력 C# 에서 MSchart는 의외로 다양한 입력형태를 제공하고 있다. 많은 편리함을 제공한다
  1. series.Points.AddXY
    private void SplineChartExample()
    {
        this.chartControl.Series.Clear();
     
        this.chartControl.Titles.Add("Total Income");
     
        Series series = this.chartControl.Series.Add("Total Income");
        series.ChartType = SeriesChartType.Spline;
        series.Points.AddXY("September", 100);
        series.Points.AddXY("Obtober", 300);
        series.Points.AddXY("November", 800);
        series.Points.AddXY("December", 200);
        series.Points.AddXY("January", 600);
        series.Points.AddXY("February", 400);
    }
  2. series.Points.AddXY
              
    public void GraphGenerate(Chart grph)
    {           DateTime[] dtx;
                double[][] DyArr = new double[2][];
                #region Data Generate
                ////////////////////////////////////////////////////////
                // Make Data
                Random r = new Random();
                DateTime start = DateTime.Parse(xtxt);
                int cnt = int.Parse(scnt);
                dtx = new DateTime[cnt];
                DyArr[0] = new double[cnt];
                DyArr[1] = new double[cnt];
                for (int i = 0; i < cnt; i++)
                {
                    dtx[i] = start.AddMinutes(5*i);
                    DyArr[0][i] = Math.Sin(Math.PI * 0.1 * i)*r.Next(-1,100);
                    DyArr[1][i] = Math.Cos(Math.PI * 0.1 * i) * r.Next(-10, 50);
                }
                #endregion
                #region Draw Chart             
                for (int i = 0; i < cnt; i++)
                {
                    sers[0].Points.AddXY(dtx[i], DyArr[0][i]);
                    sers[1].Points.AddXY(dtx[i], DyArr[1][i]);
                }
               #endregion
    }
    
  3. series.Points.DataBindXY
              
    public void GraphGenerate(Chart grph)
    {           DateTime[] dtx;
                double[][] DyArr = new double[2][];
                #region Data Generate
                ////////////////////////////////////////////////////////
                // Make Data
                Random r = new Random();
                DateTime start = DateTime.Parse(xtxt);
                int cnt = int.Parse(scnt);
                dtx = new DateTime[cnt];
                DyArr[0] = new double[cnt];
                DyArr[1] = new double[cnt];
                for (int i = 0; i < cnt; i++)
                {
                    dtx[i] = start.AddMinutes(5*i);
                    DyArr[0][i] = Math.Sin(Math.PI * 0.1 * i)*r.Next(-1,100);
                    DyArr[1][i] = Math.Cos(Math.PI * 0.1 * i) * r.Next(-10, 50);
                }
                #endregion
                #region Draw Chart            
               sers[0].Points.DataBindXY(dtx, DyArr[0]);
               sers[1].Points.DataBindXY(dtx, DyArr[1]);
               #endregion
    }
    
Graph 추가 및 속성여기서 생성된 형태는 기본적으로 chart 형태가 된다. 차트 형태의 속성을 Clear하고  Series를 추가한다음 속성을 설정하고  그래프에 표시되는  Data를 입력해 주면 된다. 그러면 Data가추가 되는 즉시 그래프를 처리 해준다. 
 
using System.Windows.Forms.DataVisualization.Charting;
public partial class FormGraph : Form
{
public FormGraph()
{
InitializeComponent();
}
private void FormGraph_Load(object sender, EventArgs e)
{
Graph.Series.Clear(); //default series를 청소한다.
Series sSin = Graph.Series.Add("sin"); //series 생성하고 생성된 series object를 가져온다
sSin.ChartType = SeriesChartType.Line; //그래프의 선 모양을 '선'으로 지정
sSin.Color = Color.Red;//Line의 색상을 설정한다

//데이터 포인트 입력
for (double k = 0; k < 2 * Math.PI; k += 0.1)
{
sSin.Points.AddXY(k, Math.Sin(k));//좌 표 X 의 값에 Y의 값을 지정
}

//Cos 그래프를 하나더 추가 하기
Series scos = Graph.Series.Add("Cos"); //series 생성하고 생성된 series object를 가져온다
scos.ChartType = SeriesChartType.Point; //그래프로 그려지는 선 모양을 '점'으로 지정
scos.Color = Color.Blue;//Line의 색상을 설정한다
scos.MarkerSize = 14;//선 두께 설정
//데이터 포인트 입력
for (double k = 0; k < 2 * Math.PI; k += 0.1)
{
scos.Points.AddXY(k, Math.Cos(k));//좌 표 X 의 값에 Y의 값을 지정
}
}
}
ChartType은 Chart의 형태를 지정할 수 있다. SeriesChartType에 정의 되어 있는 형태를 선택 할 수 있다.
    public enum SeriesChartType
    {
        Point = 0,
        FastPoint = 1,
        Bubble = 2,
        Line = 3,
        Spline = 4,
        StepLine = 5,
        FastLine = 6,
        Bar = 7,
        StackedBar = 8,
        StackedBar100 = 9,
        Column = 10,
        StackedColumn = 11,
        StackedColumn100 = 12,
        Area = 13,
        SplineArea = 14,
        StackedArea = 15,
        StackedArea100 = 16,
        Pie = 17,
        Doughnut = 18,
        .....
        Pyramid = 34
    }
chartGraph.Series(0).ChartType = (SeriesChartType)3; chartGraph.Series(1).ChartType = SeriesChartType.Line ; 와  같은 형태로 그래프 형태를 변경할 수 있다.

Chart의 축의영역  Minimum,Maximum 설정으로 표시영역설정

[Chart Axis Min and Max]

[Chart Axis Min and Max]는 X축의 Min Max를 설정했을 때 그래프가 확대되어 표시되는 것을 확인 할 수 있습니다. 소스코드에서 특이 사항은 시간 값을 문자열로 변환하고, 문자열을 합쳐서 시간연산 효과를 얻는동시에 다시 시간값으로 변환한 다음, Chart에 표시가능한 Dpuble 값으로 변환하고 있다는 것입니다.
 private void CLickMINMAX(object sender, EventArgs e)
 private void CLickMINMAX(object sender, EventArgs e)
 {
     ChartArea plots = chartGraph.ChartAreas[0];
     DateTime[] dateTime = new DateTime[2];
     //시간값을 문자열로 변환
     String[] tFmt = new String[2];
     tFmt[0] = datePickS.Value.ToString("yyyy-MM-dd") + TimePickerS.Value.ToString(" HH:mm:ss");
     tFmt[1] = datePickE.Value.ToString("yyyy-MM-dd") + datePickE.Value.ToString(" HH:mm:ss");
     //시간을 표신한 문자열을 시간값 Datetiem 으로 변환
     dateTime[0] = DateTime.Parse(tFmt[0]);
     dateTime[1] = DateTime.Parse(tFmt[1]);

     //시간(Dateime)을 Double로 변환
     plots.AxisX.Minimum = dateTime[0].ToOADate();
     plots.AxisX.Maximum = dateTime[1].ToOADate();
 }
 Zoom기능(Scroll)

Chart를 확대하려면 ChartArea.AxisX.ScaleView.Zoom(dateTime[0].ToOADate(), dateTime[1].ToOADate())를 호출하면 된다. Scroll이 자동으로 추가되며 확대된 상태에서 Point를 옮겨서 상태를 확이 할 수 있다. AxisX에서 Min,MAX를 적용한 것과 비슷 하지만, Scroll 기능이 있어서, 확대된 상태에서 다른 구간의 Graph를 볼 수 있다. 또한 Chart 좌측하단 의 (-)버튼을 누르면 이전 상태로 돌아 간다.
private void ZOOM(object sender, EventArgs e)
{
    ChartArea plots = chartGraph.ChartAreas[0];

    plots.AxisX.ScaleView.ZoomReset();

    DateTime[] dateTime = new DateTime[2];

    String[] tFmt = new String[2];
    tFmt[0] = datePickSZ.Value.ToString("yyyy-MM-dd") + TimePickSZ.Value.ToString(" HH:mm:ss");
    tFmt[1] = datePickEZ.Value.ToString("yyyy-MM-dd") + TimePickEZ.Value.ToString(" HH:mm:ss");

    dateTime[0] = DateTime.Parse(tFmt[0]);
    dateTime[1] = DateTime.Parse(tFmt[1]);

    plots.AxisX.ScaleView.Zoom(dateTime[0].ToOADate(), dateTime[1].ToOADate());
    RedrawxLabel(dateTime[0], dateTime[1]);
}
Chart에서 마우스로 확대 영역을 지정 하려면 CursorX.Interval을 변경해서 선택 영역을 변경할 수 있다. Default로 설정된 CursorX의 선택 법위를 변경하여 화면 확대 영역을 조절 할 수 있다.

소스 파일에서는 Chart에 마우스 우측 버튼이 눌러 지면 TracCursor를 활성화 하고 나서 CursorX.Interval을 변경하도록 되어 있다. ChartArea.CursorX.IsUserSelectionEnabled 에서 사용자가 선택 할 수 있도록 시켜야 하며, X,Y 축에 대해서 별개로 설정이 가능하다. CursorX.Interval은 Double값이 되어야 하며 0 이하 즉 0.001 같이 솟수점 이하로 입력해야 한다,
private void OnChartContext(object sender, EventArgs e)
{
    ChartArea plots = chartGraph.ChartAreas[0];
    MenuItem mmenuItm = (MenuItem)sender;//메뉴Item text
    switch (mmenuItm.Text)
    {
        case "Zoom-X":
            {
                mmenuItm.Checked = !plots.CursorX.IsUserSelectionEnabled;
                plots.CursorX.IsUserSelectionEnabled = mmenuItm.Checked;
                plots.CursorX.Interval = trackCursor.Value/100.1;
            }
            break;
        case "Zoom-Y":
            {
                mmenuItm.Checked = !plots.CursorY.IsUserSelectionEnabled;
                plots.CursorY.IsUserSelectionEnabled = mmenuItm.Checked;
            }
            break;
       
    }
}
private void trackCursor_Scroll(object sender, EventArgs e)
{
     ChartArea plots = chartGraph.ChartAreas[0];
     plots.CursorX.Interval = trackCursor.Value / 100.0;     
}
Grid 관련Grid는 X,Y축에 대한 눈금(축 간격)을 표시하는 항목이다 Interval=0 이면 자동으로 처리한다. 자동으로 처리되는 눈금이 적절 하지 않을때 변경하여 가독성이 좋도록 수정 한다.
  1. Axis Interval예를 들어 X 축이 정수 순으로 나열 되어있고 10000개의 Data가 있다고 가정 할 때 축 X 축 간격을 모두 표시 하면 화면이 까많게 되기 때문에 축간견을 늘려 주어야 한다. 'XAxis.Interval'을 변경하여 축 간격을 조절 할 수 있다.  쉽게 말해 축의 눈금 갯수 가 변한 것을 확인 할 수 있다. 
     
    SeriesList sList = new SeriesList();
    sList.ChartType = ChartType.Spline;
    
    sList.AxisFactor.YAxis.Visible = false; 
    
    sList.AxisFactor.XAxis.Interval = 5; //축 간격
    sList.AxisFactor.XAxis.LabelFormat.Alignment = StringAlignment.Near;
    
    sList.GraphArea.Grid.GridDirection = GridDirection.Horizontal;
    
    Random r = new Random();
    for(int i = 0; i < 1; i++)
    {
    Series sr = new Series(); 
    sr.Name = "Serie" + i.ToString();
    sr.Line.LineWidth = 2;
    sr.Points.Width = 0; 
    
    for(int x = 0; x < 15; x++)
    {
    SeriesItem item = new SeriesItem();
    item.Name = "item" + x.ToString();
    item.YValue =r.Next(943) * 0.01; 
    
    sr.items.Add(item);
    }
    sList.SeriesCollection.Add(sr);
    }
    this.hHippoChart1.PaletteType = PaletteType.Sky;
    this.hHippoChart1.SeriesListDictionary.Add(sList);
    this.hHippoChart1.DrawChart(); 
    
  2. Axis IntervalOffset축 간격의 시작 Offset을 지정할 수 있다. 그림에서와 같이 X축에 표시되는 값이 오른쪽으로 밀려서 표시되는 것을 불 수 있다. 
     
    private void xGridOffest_valuechanged(object sender, EventArgs e)
    {
       ChartArea plots = chartGraph.ChartAreas[0];
       plots.AxisX.IntervalOffset = (double)xgrid_offset.Value ;
    }
    
  3. 격자 MajorGrid축의 격자(MajorGrid)간격을 조절 할 수 있다. AxisX.Interval에서는 X축의 하단 눈금에 관련하여 간격이 조절 되었지만 MajorGrid.Interval은 Chart 내부의 격자(Grid)가 변경되는 것을 확인 할 수 있다
     
    private void xGridMajor_ValueChanged(object sender, EventArgs e)
    {
        ChartArea plots = chartGraph.ChartAreas[0];
        plots.AxisX.MajorGrid.Interval = (double)xGridMajor.Value ;
    }