본문 바로가기
Programming/Java

Java JPanel 이용한 막대차트, 꺾은선그래프, 파이차트 만들기

by wonduk 2023. 7. 13.
728x90

public void paintComponent(Graphics g){} 를 이용하면 마치 실세계의 붓의 역할처럼 

색상선택, 문자열 출력, 도형그리기, 도형칠하기, 이미지 출력, 클리핑 등이 가능합니다.

클리핑이란 이미지에서 한부분만 보여주고 나머지는 공백으로 처리하는 것 입니다.

 

draw클래스 들은 무언가를 작성하는 클래스로

draw~~~로 구현이 가능합니다.

drawString(문자열,x,y) //문자열 그리기, 왼쪽 하단을 기준으로 x,y좌표 입력
drawOval(왼쪽상단 좌표x,y, 원크기x,y)  도형의 경우에는 왼쪽 상단이 기준 좌표
drawRect(왼쪽상단 좌표x,y 사각형크기x,y)

drawArc(x,y,w,h,시작각도(3시방향이 0도임),그리는 각도(양수는 반시계방향)) //다각형그리는 클래스 
drawPolygon([]x,[]y,int n)n개만큼 연결 x.y좌표를 하나씩 지정

 

위의 코드는 테두리만 색이 칠해진 도형이며 전체적으로 색이 칠해진 코드는 draw자리에 fill로 대체하면 됩니다.

해당코드들을 활용하여 차트를 작성해볼 것인데 작성하기전에 공통적으로 들어가야 할 부분입니다.

 

public class ChartEx extends JFrame{
	
	
	public ChartEx() {
		setTitle("차트");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setContentPane(new MyPanel());
		
		setSize(800,800);
		setVisible(true);
    
    }
   //해당부분에 코드 삽입
	
    
    public static void main(String[] args) {
		new ChartEx();
	}

}

 

해당 코드들을 이용해서 분기별 매출에 대한 막대차트를 구현하면 다음과 같습니다.

			class MyPanel extends JPanel{
		
		@Override
		public void paint(Graphics g) {
			super.paint(g);
			//막대그래프
			int h = 20;
			int vGap = 10;
			int textYModify = (int)(h*0.25);
			int graphX = 120;
			int textX = 50;
			int hGap = 100;
			
			//분기별 매출액입력 1분기-2분기,3분기,4분기
			int[] sales = {100,300,120,350};
			
			
			g.drawString("1/4분기", textX, 20+h-textYModify); //y값 + y값하면 글자위치 적기가능
			g.setColor(Color.red);
			g.fillRect(graphX, 20, sales[0], h);// 매출이 100억 높이가 20
			
			g.setColor(Color.black);
			g.drawString("2/4분기", textX, 20+h+(h+vGap)-textYModify); //y값 + y값하면 글자위치 적기가능
			g.setColor(Color.orange);
			g.fillRect(graphX, 20+h+vGap, sales[1], h);// 매출이 100억 높이가 20

			g.setColor(Color.black);
			g.drawString("3/4분기", textX, 20+h+(h+vGap)*2-textYModify); //y값 + y값하면 글자위치 적기가능
			g.setColor(Color.yellow);
			g.fillRect(graphX, 20+(h+vGap)*2, sales[2], h);// 매출이 100억 높이가 20

			g.setColor(Color.black);
			g.drawString("4/4분기", textX, 20+h+(h+vGap)*3-textYModify); //y값 + y값하면 글자위치 적기가능
			g.setColor(Color.green);
			g.fillRect(graphX, 20+(h+vGap)*3, sales[3], h);// 매출이 100억 높이가 20

차트의 경우 자동화를 해 두는 것이 나중에 유지보수에 유리하기 때문에

분기별 매출액을 sales에 배열로 담고,

x와 y로 좌표값을 설정하며, vGap, hGap으로 막대간 위치간격을 조절하며, 20+(h+vGap)로 기본 위치를 정해준 후 

곱하기를 통해 막대위치를 추가적으로 늘릴 수 있습니다.

 


 

 

 

다음은 꺾은선 그래프입니다.

class MyPanel extends JPanel{
		
		@Override
		public void paint(Graphics g) {
			super.paint(g);
			//막대그래프
			int h = 20;
			int vGap = 10;
			int textYModify = (int)(h*0.25);
			int graphX = 120;
			int textX = 50;
			int hGap = 100;
			
			//분기별 매출액입력 1분기-2분기,3분기,4분기
			int[] sales = {100,300,120,350};
            
            //꺾은 선 그래프

			//그래프 초기 위치값
			int y = 600;
			int x = 20;
			int strX = 20;
			int comma = 5;
			int count = 1;
			
			g.setColor(Color.black);
			g.drawLine(x+(hGap)*(count-1), y, 20+hGap, y-sales[count-1]); //1/4 선
			g.setColor(Color.red);
			g.drawString("1/4분기",(20+hGap)*count+comma, y-sales[count-1]); //1/4 점 옆에 글자
			g.drawString("1/4분기",(20+hGap)*count+comma-strX, y+strX); //1/4 x축의 글자
			
			
			count++;
			
			g.setColor(Color.black);
			g.drawLine(x+(hGap)*(count-1), y-sales[count-2], 20+hGap*count, y-sales[count-1]);  // 2/4
			g.setColor(Color.red);
			g.drawString("2/4분기",(20+hGap*count)+comma, y-sales[count-1]); //1/4 점 옆에 글자
			g.drawString("2/4분기",(20+hGap*count)+comma-strX, y+strX); //1/4 x축의 글자
			

			count++;
			
			g.setColor(Color.black);
			g.drawLine(x+(hGap)*(count-1), y-sales[count-2],20+hGap*count, y-sales[count-1]); // 3/4
			g.setColor(Color.red);
			g.drawString("3/4분기",(20+hGap*count)+comma, y-sales[count-1]); //1/4 점 옆에 글자
			g.drawString("3/4분기",(20+hGap*count)+comma-strX, y+strX); //1/4 x축의 글자
			
			count++;
			
			g.setColor(Color.black);
			g.drawLine(x+(hGap)*(count-1), y-sales[count-2],20+hGap*count, y-sales[count-1]); // 4/4
			g.setColor(Color.red);
			g.drawString("4/4분기",(20+hGap*count)+comma, y-sales[count-1]); //1/4 점 옆에 글자
			g.drawString("4/4분기",(20+hGap*count)+comma-strX, y+strX); //1/4 x축의 글자
			
			
			g.setColor(Color.black);
			g.drawLine(x, y, x+hGap*count, y);//가로 선
			g.drawLine(x, y, x, y-sales[3]);//세로 선
			g.drawString("단위:억", x, y-sales[3]);
			g.drawString("분기", x+hGap*count, y);
          }
      }

꺾은선 그래프의 경우g.drawLine에서 x좌표와 y좌표를 기본설정을 해준 다음 x좌표에 hGap+ sales만큼 곱해주고

작성할 때 count ++;만 해주어서 자동적으로 위치가 생성되도록 작성하였습니다.

이후 그래프가 생겨날 경우에는 배열에 값을 넣고 count++을 해준 후 코드 g.draw코드 5줄을 추가하면 자동으로 생성되도록 작성했습니다.

 

 


 

 

 

다음은 파이차트입니다.

//파이차트
			//1사분기 부터 4사분기까지가 합한게 360이여야 함 (공식만들기)
			
			//차트크기,위치
			int px = 450;
			int py = 400;
			int pw = 300;
			int ph = 300;
			int sum = 0;//매출 합산값
			int[] angle = new int[4]; //매출 인덱스별 각도값
			
			for (int i = 0; i < sales.length; i++) {
				 sum += sales[i];
				 }
			for (int i = 0; i < sales.length; i++) {
				angle[i]= (int)Math.round((sales[i]*100000/870*360)/100000);  
			}
						
			g.setColor(Color.red);
			g.fillArc(px, py, pw, ph, 0, angle[0]); //1분기
			g.drawString("1분기", px+pw, py-(vGap*2)*0);
			g.setColor(Color.blue);
			g.fillArc(px, py, pw, ph, angle[0], angle[1]); //2분기
			g.drawString("2분기", px+pw, py-(vGap*2)*1);
			g.setColor(Color.green);
			g.fillArc(px, py, pw, ph, angle[0]+angle[1], angle[2]); //3분기
			g.drawString("3분기", px+pw, py-(vGap*2)*2);
			g.setColor(Color.yellow);
			g.fillArc(px, py, pw, ph, angle[0]+angle[1]+angle[2],
					angle[3]+(360-angle[0]-angle[1]-angle[2]-angle[3]));// 4분기, 오차범위로 인해 생긴 여백 채우기
			g.drawString("4분기", px+pw, py-(vGap*2)*3);
			
			
		}
	}

파이차트도 각도별로 for문을 통해 구해놓았기 때문에 

g.setColor, g.fillArc, g.drawString 3줄을 넣고 3번째","지점에 angle[i]값을 하나 더 넣어주고 마지막 fillArc코드에 마지막","에서 angle[i]값을 추가해주면 됩니다.

728x90