TYPE_MAGNETIC_FIELD는 지구 자기장의 강도를 수치로 보여주는 센서로 주변 금속의 강도에 따라 맴돌이 전류가 발생하여

자기장이 영향을 받는 것을 이용해 간단한 금속탐지기 기능을 구현해 봅니다.


지자기장은 지구의 위치마다 달라 20~80정도로 차이가 발생하고 한국은 50정도 입니다.

좀더 성능 좋은 금속탐지기를 만들려면 TYPE_MAGNETIC_FIELD_UNCALIBRATED 센서를 이용해서

원래의 값을 받아와 보정 작업을 진행해야 합니다.



1 자기장 센서


1.1 자기장 센서 이벤트 값


TYPE_MAGNETIC_FIELD 센서가 작동 되면 리턴되는 값으로 다음과 같은 value를 넘겨 주며 단위는 μT(마이크로 테슬라)입니다.

리턴된 값은 센서에서 보내주는 값들을 자체 보정 해서 나온 수치 입니다.


Sensor

 Sensor event data

 표현 값

 측정 단위

 TYPE_MAGNETIC_FIELD

 SensorEvent.values[0]

 x축 지구자장 강도

 μT

 TYPE_MAGNETIC_FIELD

 SensorEvent.values[1]

 y축 지구자장 강도

 μT

 TYPE_MAGNETIC_FIELD

 SensorEvent.values[2]

 z축 지구자장 강도

 μT



2 자기장 센서 프로젝트

 

2.1 신규 프로젝트 생성


안드로이드 스튜디오에서 적당한 이름으로 프로젝트를 하나 생성합니다.



2.2 Layout 작성


activity_main.xml

 

자기장 센서가 보내오는 x, y, z축의 μT값들을 출력할 수 있는 TextView를 작성합니다.

그리고 간략한 금속 탐지 기능을 보여줄 TextView도 하나 생성 합니다.


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Megnetic Value"
        android:layout_marginTop="50dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tvXaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="X axis : 0"
        />
    <TextView
        android:id="@+id/tvYaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvXaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Y axis : 0"
        />
    <TextView
        android:id="@+id/tvZaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvYaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Z axis : 0"
        />
    <TextView
        android:id="@+id/tvMagnetic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvZaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Magnetic : 0"
        />

</android.support.constraint.ConstraintLayout>



2.3 Java Source

 

MainActivity.java


소스를 보면 알겠지만 기존 센서와 동일한 프로세스로 작동이 됩니다.

자세한 설명은 생략 합니다. 기존 센서 예제를 확인 하세요.

onCreate에서 Sensor.TYPE_MAGNETIC_FIELD를 설정 하고 onSensorChanged에서 x, y, z 축의 magnetic 값을 받아와 출력 합니다.


지자기 총량을 구하는 공식은

Math.sqrt((magX * magX) + (magY * magY) + (magZ * magZ))

입니다.


package com.example.desk.sensormagnetic;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager sensorManager;
    private Sensor magSensor;
    int rotation;
    TextView tvXaxis, tvYaxis, tvZaxis, tvMagnetic;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvXaxis = (TextView)findViewById(R.id.tvXaxis);
        tvYaxis = (TextView)findViewById(R.id.tvYaxis);
        tvZaxis = (TextView)findViewById(R.id.tvZaxis);
        tvMagnetic = (TextView)findViewById(R.id.tvMagnetic);

        sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        magSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor ==magSensor) {
            float magX = event.values[0];
            float magY = event.values[1];
            float magZ = event.values[2];
            double magnitude = Math.sqrt((magX * magX) + (magY * magY) + (magZ * magZ));

            tvXaxis.setText("X axis : " + String.format("%.2f", magX));
            tvYaxis.setText("Y axis : " + String.format("%.2f", magY));
            tvZaxis.setText("Z axis : " + String.format("%.2f", magZ));
            tvMagnetic.setText("Magnetic : "  + String.format("%.2f", magnitude) + " \u00B5Tesla");
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}


µ를 나타내기 위해 사용한 u00B5는 유니코드입니다.

인터넷에서 유니코드를 검색하면 표로 잘 나와있어서 앞자리+윗자리 숫자를 조합해서 사용하면 됩니다.


위키 백과사전에서 조금 뜯어왔습니다.


magnetic field sensor



3. 결과


3.1 결과 화면


프로젝트를 실제 핸드폰에서 테스트한 결과 화면인데요.

책상 위에 놓았을 때 하고 컴퓨터 위에 놓았을 때의 값을 비교해보고

책상 위에서 자석을 위치 했을 때의 값을 비교해 보았습니다.

방구석에 처박혀 있을 때 켜놓고 이리저리 굴러다니며 테스트하면 나름 재미있습니다.


magnetic field sensor

magnetic field sensor



3.2 Source Code

 

 

SensorMagnetic.7z



3.3 APK File


SensorMagnetic.apk


- copy coding -

 

안드로이드 핸드폰 뿐만 아니라 대부분의 이동형 장치는 위치에 따라 기본 방향이 설정되어 있습니다. 

이걸 기준으로 화면 자동 회전을 설정해 놓아 사진 가로보기가 가능 합니다.

동서남북을 가리키는 나침반은 방향을 바꾸면 그에 맞추어 위치를 다시 계산해야 합니다.

일반적인 컴퓨터 모니터는 우측상단이 원점이고 가로 방향이 x, 세로 아래 방향이 y축이지만

Android 기기 에서는 일반적인 수학에서 배운 대로 가로 방향이 x, 세로 방향이 y, 나를 향하는 전면 방향을 z축으로 설정 합니다.

좌표 축은 이렇게 설정이 되어 있지만 장치가 세로로 있을 때 우측(가로) 방향이 x축 일까요?

태블릿 장치는 가로로 있을 때 우측 방향이 x축 일까요?


Android를 사용하는 모든 기기가 동일 하지 않다고 하니 방향과 축에 관련된 앱을 개발하려면 한번쯤 확인을 하는게 좋을 듯 합니다.



1. 상수 값


방향 확인을 위해 장치가 어느 방향으로 회전 되어 있는가를 확인하는 상수 값이 있습니다.


 Type

 Constants

 value

 설명

 int

 Surface.ROTATION_0

 0

 장치가 사용자 기준 정방향

 int

 Surface.ROTATION_90

 1

 장치가 사용자 기준 반 시계방향 90도 회전

 int

 Surface.ROTATION_180

 2

 장치가 사용자 기준 반 시계방향 180도 회전

 int

 Surface.ROTATION_270

 3

 장치가 사용자 기준 반 시계방향 270도 회전

 int

 SensorManager.AXIS_X

 1

 X축에 해당하는 상수 값

 int

 SensorManager.AXIS_Y

 2

 Y축에 해당하는 상수 값

 int

 SensorManager.AXIS_Z

 3

 Z축에 해당하는 상수 값

 int

 SensorManager.AXIS_MINUS_X

 129

 X축 반대 방향에 해당하는 상수 값

 int

 SensorManager.AXIS_MINUS_Y

 130

 Y축 반대 방향에 해당하는 상수 값

 int

 SensorManager.AXIS_MINUS_Z

 131

 Z축 반대 방향에 해당하는 상수 값



2. 회전 결과


먼저 앱을 실행하였을 때의 결과를 보면 간단하게 확인이 가능 합니다.

앱을 켜고 핸드폰을 좌측으로 한 바퀴, 우측으로 한 바퀴 돌리며 결과를 보면

반 시계방향으로 90도씩 증가하는 하며 180도 에서는 어느 방향으로 돌렸는가에 따라

90, 270도의 결과가 그대로 유지 됩니다.


android gyroscope sensor



3. 화면 회전 프로젝트

 

실제 프로젝트 하나를 만들어 보겠습니다.

 

3.1 신규 프로젝트 생성


Android studio에서 새로운 프로젝트를 생성합니다. 여기서는 SurfaceRotation로 했습니다.

캡처 화면은 팝업을 축소하여 받은 것으로 실제 화면의 일부분 입니다.




3.2 장치 설정


앱이 실행될 기본 장치를 알맞게 선택 합니다.




3.3 Configure


기본 화면은 empty를 선택 했고 코딩용 설정 값은 기본값을 그대로 사용 합니다.



 

3.4 Layout 작성


x, y 축의 값을 보여주고 회전 각을 표시하기 위한 TextView를 축의 개수에 맞게 생성 합니다.


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Surface Rotation"
        android:layout_marginTop="50dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tvXaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="X axis : 0"
        />
    <TextView
        android:id="@+id/tvYaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvXaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Y axis : 0"
        />
    <TextView
        android:id="@+id/tvZaxis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvYaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Z axis : 0"
        />
    <TextView
        android:id="@+id/tvRotation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvZaxis"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Rotation : 0"
        />

</android.support.constraint.ConstraintLayout>


3.5 Java Source


소스는 일반적인 센서 테스트용 프로젝트와 동일한 구조를 갖고 있습니다.

센서는 TYPE_GYROSCOPE를 사용 했는데 별의미 없으므로 다른 센서를 사용해도 됩니다.

화면 회전에 대한 값을 구하기 위한 getSurfaceRotation() 함수가 추가되었습니다.

이 함수에서 화면에 값을 출력 합니다.


package com.example.desk.surfacerotation;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.WindowManager;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity  implements SensorEventListener {

    private SensorManager sensorManager;
    private Sensor gyroSensor;
    int rotation;
    TextView tvXaxis, tvYaxis, tvZaxis, tvRotation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvXaxis = (TextView)findViewById(R.id.tvXaxis);
        tvYaxis = (TextView)findViewById(R.id.tvYaxis);
        tvZaxis = (TextView)findViewById(R.id.tvZaxis);
        tvRotation = (TextView)findViewById(R.id.tvRotation);

        sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

    }

    void getSurfaceRotation() {
        String windowsService = Context.WINDOW_SERVICE;
        WindowManager windowManager = (WindowManager)getSystemService(windowsService);
        Display display = windowManager.getDefaultDisplay();
        rotation = display.getRotation();

        int xAxis = SensorManager.AXIS_X;
        int yAxis = SensorManager.AXIS_Y;
        int zAxis = SensorManager.AXIS_Z;

        switch (rotation) {
            case Surface.ROTATION_0:
                tvRotation.setText("Rotation : 0");
                break;
            case Surface.ROTATION_90:
                xAxis = SensorManager.AXIS_Y;
                yAxis = SensorManager.AXIS_MINUS_X;
                tvRotation.setText("Rotation : 90");
                break;
            case Surface.ROTATION_180:
                yAxis = SensorManager.AXIS_MINUS_Y;
                tvRotation.setText("Rotation : 180");
                break;
            case Surface.ROTATION_270:
                xAxis = SensorManager.AXIS_MINUS_Y;
                yAxis = SensorManager.AXIS_X;
                tvRotation.setText("Rotation : 270");
                break;
            default:
                break;
        }
        tvXaxis.setText("X axis : " + String.valueOf(xAxis));
        tvYaxis.setText("Y axis : " + String.valueOf(yAxis));
        tvZaxis.setText("Z axis : " + String.valueOf(zAxis));
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, gyroSensor, SensorManager.SENSOR_DELAY_FASTEST);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor ==gyroSensor) {
            getSurfaceRotation();
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}


4. 결과


4.1 결과 화면


위에서 회전각을 표시한 그림과 같은 결과들을 볼 수 있습니다.



3.2 Source Code

소스코드를 첨부 합니다.


SurfaceRotation.7z



 

3.3 APK File

직접 테스트 하려면 apk를 이용 하세요.


SurfaceRotation.apk


- copy coding -


TYPE_LIGHT는 빛의 세기를 전기적 신호로 변경하여 수치로 보여주는 센서로

핸드폰의 앞면에 위치하고 화면의 자동 밝기 자동 조절등에 사용 되는 기능 입니다.



1 광 센서


1.1 광 센서 이벤트 값


센서가 작동 되면 리턴되는 값으로 한 개의 value를 넘겨 주며 단위는 lux(lx) 입니다.


 Sensor

 Sensor event data

 표현 값

 측정 단위

 TYPE_LIGHT

 SensorEvent.values[0]

 물체의 밝기

 lx



1.2 설정 상수 값



광 센서가 리턴하는 값은 float 값으로 나타나며 일부 설정되어 있는 상수 값은 아래 표와 같습니다.


Type

 상수

 값

 float

 LIGHT_CLOUDY

 100.0

 float

 LIGHT_FULLMOON

 0.25

 float

 LIGHT_NO_MOON

 0.001

 float

 LIGHT_OVERCAST

 10000.0

 float

 LIGHT_SHADE

 20000.0

 float

 LIGHT_SUNLIGHT

 110000.0

 float

 LIGHT_SUNLIGHT_MAX

 120000.0

 float

 LIGHT_SUNRISE

 400.0



2 광센서 프로젝트



2.1 신규 프로젝트 생성


안드로이드 스튜디오에서 프로젝트를 하나 생성합니다.



2.2 AndroidManifest.xml


Google play에서는 앱을 다운로드 하기 전에 해당 기능을 실행할 장치가 있는지 확인하여


장치가 없으면 실행을 할 수 없도록 제한 하고 있습니다.


<uses-feature>를 설정하고 값을 false로 하면 장치가 없어도 앱을 다운받아 실행 할 수 있도록 할 수 있습니다.


<uses-feature android:name="android.hardware.sensor.light" android:required="false"/>


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.desk.lightsensor">

    <uses-feature android:name="android.hardware.sensor.light" android:required="false"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>



2.3 Layout 작성


activity_main.xml


 센서가 보내오는 lux값을 출력할 수 있는 TextView를 작성합니다.


tvTitle TextView는 고정해서 Proximity Sensor를 출력 하고 센서로부터 받아온 값은 tvLight TextView에 출력 합니다.


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Light Sensor"
        android:layout_marginTop="50dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tvLight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="25dp"
        android:text="Light : 0"
        />
</android.support.constraint.ConstraintLayout>



2.4 Java Source


소스를 보면 알겠지만 기존 센서와 동일한 프로세스로 작동이 됩니다.


자세한 설명은 생략 합니다. 기존 센서 예제를 확인 하세요.


onCreate에서 TYPE_LIGHT를 설정 하고 onSensorChanged 에서 조도 값을 받아와 출력 하면 됩니다.


package com.example.desk.lightsensor;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager sensorManager;
    private Sensor lightSensor;
    TextView tvLight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvLight = (TextView)findViewById(R.id.tvLight);
        sensorManager =(SensorManager)getSystemService(Context.SENSOR_SERVICE);
        lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
        if(lightSensor == null) {
            Toast.makeText(this, "No Light Sensor Found!", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_LIGHT) {
            tvLight.setText("Light : " + String.valueOf(event.values[0]));
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

}



3. 결과


3.1 결과 화면


프로젝트를 실행 실제 핸드폰에서 테스트한 결과 아래와 같은 화면이 나옵니다.


우리집 거실이 어두운 편이네요.


android light sensor



3.2 Source Code


압축을 풀어서 사용하세요.


LightSensor.7z




3.3 APK File


그냥 확인만 해보려면 사용해 보세요.


LightSensor.apk


- copy coding -


codejock과 더불어 많이 사용하고 있는 bcgsoftBCGControlBar Library를 가지고 간단한 Chart를 하나 그려 보면서 사용법을 알아 보도록 하겠습니다.



1. 프로젝트 생성


BCGControllerBar를 설치 했으면 적당한 이름으로 프로젝트를 생성해 줍니다.



계속 [다음] 버튼을 누르다 보면 설정들이 일반 MFC 프로젝트와 비슷하지만 종류가 많아진 것을 알 수 있는데

그냥 Single Document를 선택하고 모두 [다음] 버튼을 선택해서 넘어 갑니다.

그리고 프로젝트 생성 마지막 단계에서 Base classCBCGPFormView 를 선택해 주고 [Finish] 버튼을 선택 합니다.




2. BCG 추가하기


프로젝트가 생성이 되었으면 이제 본격적으로 차트를 그려보도록 하겠습니다.

- 리소스 뷰에서 main FORM 을 선택합니다.

- Form Picture Control을 하나 적당하게 그려 넣어 줍니다.

- 속성 값에

       Type : Rectangle

         Color : Gray

를 선택 합니다. ID는 편한대로 하고 저는 IDC_CHART로 했습니다.



프로젝트를 저장 하고 코딩을 하기 전에 프로젝트가 제대로 생성되었는지 일단 실행 해볼까요?

저는 코딩 하기 전에 한번 환경이 잘 잡혔는지 잘못 입력된 부분이 있는지 시행을 해봅니다.



이런오류가 뜨는 군요.

BCGControlbarx64로 설치하고 x86으로 실행을 해서 발생한 오류 입니다.

이유를 찾느라 시간을 좀 허비 했었는데 나같은 사람을 없겠죠.


설정 값만 x64로 변경하고 실행하면 이번엔 오류 없이 잘 나옵니다.

아직은 chart를 그리지 않아서 회색의 빈 공간으로 나타나지만 계획대로 잘 나왔습니다.




3. 코딩


BCGPieChartView.h 헤더 파일에 다음 항목을 정의 합니다.


public:
	CBCGPChartCtrl		m_PieChart;

	int   m_nHoleSize;
	CString	m_strHoleSize;

	void UpdatePieChart();

BCGPieChartView.cpp 소스 파일에 그리기 코딩 작업을 합니다.


CBCGPieChartView() 함수에 헤더에서 정의한 변수의 기본값을 설정 합니다.

CBCGPieChartView::CBCGPieChartView()
	: CBCGPFormView(CBCGPieChartView::IDD)
{

	EnableVisualManagerStyle();

	// TODO: add construction code here
	m_nHoleSize = 50;
	m_strHoleSize = _T("");

	m_strHoleSize.Format(_T("%d%%"), m_nHoleSize);

}

form에 그렸던 picture controll을 연결 합니다.

void CBCGPieChartView::DoDataExchange(CDataExchange* pDX)
{
	CBCGPFormView::DoDataExchange(pDX);

	DDX_Control(pDX, IDC_CHART, m_PieChart);
}

이제 차트를 그리기 위한 초기 설정 값들을 적어줍니다.

void CBCGPieChartView::OnInitialUpdate()
{
	CBCGPFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();

	//Pie Draw
	CBCGPInfoTipOptions infoTipOptions;
	infoTipOptions.m_StemLocation = CBCGPPopupWindow::BCGPPopupWindowStemLocation_Left;

	m_PieChart.EnableInfoTip(TRUE, &infoTipOptions);


	CBCGPChartVisualObject* pChart = m_PieChart.GetChart();

	ASSERT_VALID(pChart);

	pChart->ShowDataLabels(TRUE);
	pChart->SetChartType(BCGPChartPie);  //차트 종류를 기입하는곳 입니다.
	pChart->SetRect(CRect(0, 0, 200, 200), TRUE);


	pChart->SetLegendPosition(BCGPChartLayout::LP_NONE, FALSE, FALSE);
	pChart->SetChartTitle(_T("Test PieChart"));  //차트상단 타이틀입니다.
	pChart->AddChartData(_T("Apple"), 60);    //이건 아시죠? 차트별 값
	pChart->AddChartData(_T("Orange"), 20);
	pChart->AddChartData(_T("Banana"), 20);

	UpdatePieChart();
}

차트 초기값 설정이 끝났으니 차트를 그리는 부분을 코딩합니다.

차트 설정가 그리는 부분을 나눈 이유는 아시죠?

차트 값이 변경되면 다시 그리는 부분이라고 생각하시면 어떻게 응용해야 하는지 감을 잡았겠죠.

void CBCGPieChartView::UpdatePieChart()
{
	UpdateData();

	CBCGPChartVisualObject* pChart = m_PieChart.GetChart();
	ASSERT_VALID(pChart);

	BCGPChartDataLabelOptions dataLabelOptions = pChart->GetDataLabelOptions();
	dataLabelOptions.m_position = BCGPChartDataLabelOptions::LabelPosition::LP_CENTER;
	dataLabelOptions.m_bUnderlineDataLabel = TRUE;
	dataLabelOptions.m_content = BCGPChartDataLabelOptions::LC_PIE_NAME_PERCENTAGE;
	dataLabelOptions.m_bDrawDataLabelBorder = dataLabelOptions.m_position != BCGPChartDataLabelOptions::LP_DEFAULT_POS && dataLabelOptions.m_position != BCGPChartDataLabelOptions::LP_OUTSIDE_END;

	pChart->SetDataLabelsOptions(dataLabelOptions);
	pChart->Redraw();
}

여기서는 그냥 간단히 차트를 하나 그리는것만 하였습니다.


실제로 설정값들이 여러가지 있습니다. 그건 하나씩 변경하면서 어떻게 결과가 나오는지 확인해 보면서 익히셔야 합니다.


여기까지의 코딩 결과를 실행해 보면 아래처럼 파이차트가 나타납니다.



간단히 legend를 안보이게 하면 아래처럼


BCGControlbar PieChart



끝입니다.


- copy coding -


1···113114115116117118

+ Recent posts