4개의 축

축은 차트의 가장자리에 표시되는 눈금이다. ChartArea에 소속되며 Axes 속성의 컬렉션 편집기를 열어 보면 축의 목록이 나타난다.

가로쪽이 X축이고 세로쪽이 Y축이며 양쪽으로 각각 붙일 수 있어 에리어당 총 4개의 축이 있다. 편집기에서 보다시피 4개의 축이 미리 등록되어 있으며 더 만들거나 삭제할 수는 없고 속성만 조정할 수 있다.

축의 여러 가지 속성을 테스트해 보기 위해 가로축을 시간으로 하는 차트를 만들어 보자. 

 

private void Form1_Load(object sender, EventArgs e)

{

       chart1.Legends[0].Enabled = false;

       Random R = new Random(100);

       DateTime dt = new DateTime(2020, 10, 1, 9, 0, 0);

       for (int i = 0;i<20;i++)

       {

                  chart1.Series[0].Points.AddXY(dt, R.Next(10, 100));

                  dt = dt.AddMinutes(1);

       }

}

 

오전 9시부터 1분 간격으로 10~100 사이의 난수로 차트를 그렸다. 세로축은 점수라고 생각하면 된다. 이 코드 아래쪽에 속성을 조정하는 코드를 작성하여 실습을 진행한다.

아래쪽이 X축이며 시간을 보여 준다. 왼쪽이 Y축이며 0 ~ 100까지 20 간격으로 값을 표시한다. 축에는 다음 요소가 배치된다.

 

틱마크 : 정확한 위치를 표시하는 선이다. 위 그림의 Y축을 보면 20, 40, 60 자리에 왼쪽으로 약간 삐져 나온 직선이 틱마크이다.

레이블 : 위치나 값을 설명하는 문자열이다. Y축의 20, 40이나 X축의 날짜가 레이블이다. 주기, 포맷, 속성 등에 따라 모양이 천차 만별로 달라진다.

그리드 : 차트의 플롯 영역에 표시되는 바둑판 모양의 격자이다. 틱마크가 플롯 영역으로 확장된 것이다.

 

디폴트로 X축은 아래쪽, Y축은 왼쪽만 표시되어 있어 2개의 주축만 보인다. 오른쪽과 위쪽에도 보조축이 있지만 숨겨져 있다. 이 축도 보이도록 해 보자. 아래쪽에 다음 코드를 작성한다.

 

chart1.ChartAreas[0].AxisX2.Enabled = AxisEnabled.True;

chart1.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;

 

AxisX2AxisY2 축의 Enabled 속성을 True로 변경하면 축이 보인다. 이 속성을 Auto로 지정하면 차트의 타입이나 시리즈의 특성에 따라 자동으로 보임 여부를 결정한다. 축 객체의 이름을 지정하는 대신 에리어의 Axes 속성의 첨자를 통해 Axes[2], Axes[3]로 칭해도 효과는 같다.

오른쪽과 위쪽에도 축이 나타난다. 차트가 아주 크다면 축이 양쪽에 다 있는 것이 보기는 편리하지만 번잡스러워 보통은 주축만 표시한다.

축은 차트 플롯을 가리지 않도록 가장자리에 놓는 것이 무난하지만 필요하다면 플롯 중간에 놓을 수도 있다. 축의 Crossing 속성은 상대축과 교차할 지점을 지정하는데 디폴트값은 NaN이며 이 경우 자동으로 적당한 곳에 배치된다.

double.MinValue로 지정하면 가장 작은값 쪽에 배치되고 double.MaxValue로 지정하면 가장 큰값쪽에 배치된다. 중간의 적당한 값으로 지정하면 해당 위치에 상대축이 배치된다. AxisYCrossing 속성으로 50 정도로 지정해 보자.

 

chart1.ChartAreas[0].AxisY.Crossing = 50;

 

Y축의 범위는 0 ~ 100까지인데 50으로 지정하면 상대축인 X축이 딱 중간 위치에 배치된다.

이렇게 되면 50보다 더 작은 값은 막대가 아래쪽으로 그려진다. Crossing 속성을 double.MaxValue로 지정하면 X축이 최대값인 100 자리로 올라가고 모든 막대는 아래쪽으로 뻗는다.

레이블의 포맷은 시리즈의 타입에 따라 자동으로 결정되는데 시간인 경우는 날짜가 디폴트로 되어 있다. 그래서 X축의 날짜값이 모두 같아 구분이 잘 되지 않는다. 예제의 차트는 분 단위이므로 날짜가 아닌 시간 포맷으로 표시하는 것이 더 좋다. 레이블의 포맷은 축의 LabelStyle.Format 속성으로 지정한다. 다음 코드를 작성해 보자.

 

Axis ax = chart1.ChartAreas[0].AxisX;

Axis ay = chart1.ChartAreas[0].AxisY;

ax.LabelStyle.Format = "HH:mm";

 

X, Y 양쪽으로 두 축의 속성을 계속 바꿔 볼 것이므로 주축에 대한 참조를 ax, ay로 미리 구해 두었다. 컬렉션에 의한 중첩이 워낙 깊다 보니 자주 사용하는 객체는 참조를 따로 구한 후 사용하는 것이 편리하다. ax의 레이블 포맷을 HH:mm으로 표시하면 시:분 만 레이블에 표시된다.

이제 X축의 시간이 서로 구분된다. "HH:mm:ss"로 붙이면 초단위도 나타나지만 이 차트의 데이터가 분단위여서 별 의미가 없다.

차트는 5분 간격으로 틱마크와 레이블을 하나씩 표시한다. 모든 X값에 레이블을 일일이 배치할 공간이 충분하지 않아 적당히 건너 뛴다. 심지어 차트를 확대하거나 축소해도 이 간격을 유지한다. 차트의 크기와 레이블의 간격은 IntervalAutoMode 속성으로 지정하는데 이 속성의 디폴트가 FixedCount이기 때문이다. 이 속성을 VariableCount로 변경해 보자.

 

ax.IntervalAutoMode = IntervalAutoMode.VariableCount;

ay.IntervalAutoMode = IntervalAutoMode.VariableCount;

 

X, Y 양축 모두 가변 개수로 변경하였다. 이 상태에서 차트의 크기를 조정해 보면 크기에 따라 레이블의 간격과 개수가 달라진다.

 

자리가 좁으면 레이블을 조금만 보여 주고 넉넉하게 넓으면 가급적 많은 레이블을 보여준다. 데이터 개수가 가변적이고 차트 크기도 자주 바뀐다면 이 방식이 유리하지만 일관성이 없는 것은 단점이다.

레이블의 주기를 강제로 지정하려면 IntervalType, Interval 속성을 사용한다. Interval은 주기를 지정하며 이 값마다 레이블이 하나씩 표시된다. 단 값이 시간이면 Interval이 어떤 단위인지를 IntervalType으로 밝힌다. IntervalAutoMode는 해제하고 다음 코드를 작성해 보자.

 

ax.IntervalType = DateTimeIntervalType.Minutes;

ax.Interval = 2;

ay.Interval = 10;

 

X축은 매 2분마다 레이블을 표시하고 Y축은 매 10마다 레이블을 표시하라고 지시했다.

지시한대로 정확하게 레이블이 표시된다. 심지어 크기를 줄여도 레이블을 지그재그로 겹치거나 세로로 세워서라도 이 간격을 유지한다.

폼을 더 작게 줄이면 레이블끼리 겹치기도 한다. 웬만하면 자동으로 결정하도록 내버려 두는 것이 편리하지만 강제로 지정하면 이 지시를 가급적 지키기 위해 애쓴다.

축의 모양을 지정하는 속성은 직관적이고 쉽다. 대부분 색상이나 선모양, 타이틀 등의 속성은 단순한 장식이어서 코드를 작성해 보면 쉽게 이해할 수 있다.

 

속성

설명

Title

축의 제목이다.

TitleAlignment

제목의 정렬 방향이다. 디폴트는 Center이며 Near는 가까운 쪽, Far는 먼쪽이다. 좌우, 상하가 아닌 이유는 가로, 세로에 따라 방향이 다르고 우에서 좌로 읽는 레이아웃도 있기 때문이다.

TitleFont

제목의 폰트

TitleForeColor

제목의 색상

TextOrientation

제목의 방향. 디폴트는 차트 타입에 따라 자동으로 결정하는 Auto이되 수평, 90도 회전, 270도 회전, 쌓기 등이 있다.

ArrowStyle

축 끝의 화살표 모양이다. 디폴트는 None이며 Line은 화살표 모양, Triangle은 삼각형, ShartTriangle은 길쭉한 삼각형이다.

Enabled

사용 여부이다. 이 값이 false이면 축의 요소는 모두 표시되지 않는다. 주축도 없애 버릴 수 있다.

LineColor

선색상

LineWidth

선 굵기

LineDashStyle

선 모양

IsReserved

축의 방향을 반대로 뒤집는다.

IsMarginVisible

축 끝에 약간의 마진을 줄 것인가를 지정한다.

 

선모양을 바꾸고 축에 제목을 붙여 보자.

 

ax.LineColor = Color.Green;

ax.LineWidth = 3;

ax.ArrowStyle = AxisArrowStyle.Triangle;

ay.ArrowStyle = AxisArrowStyle.Lines;

 

ax.Title = "날짜";

ay.Title = "점수";

ay.TextOrientation = TextOrientation.Horizontal;

IsReversed 속성은 축의 방향을 반대로 뒤집는다. ax.IsReversed = true; 대입문을 추가하면 X축의 시간이 좌에서 우로가 아닌 우에서 좌로 증가한다.

IsMarginVisible 속성은 끝 부분에 약간씩 여백을 주는데 디폴트는 true이다.

 

ax.IsMarginVisible = false;

ay.IsMarginVisible = false;

 

이 값을 false로 변경하면 여백이 사라지고 너무 꼭 맞게 그려져 답답해 보인다. 대개의 경우는 마진이 있는 것이 무난하다. 데이터 수가 대단히 많고 가장자리의 값이 그다지 중요치 않다면 마진을 없애는 것이 보기 좋다.

X축의 첫 항목은 막대가 반으로 잘려 보이고 Y축은 100점이 없다. 대부분의 속성은 이런 식으로 값을 바꿔가며 차이점을 관찰해 보면 쉽게 이해할 수 있다. 글만 읽어서는 따분하지만 속성을 바꿔 가며 실습해 보면 나름 재미도 있고 속성의 의미를 분명히 알 수 있다.