본문 바로가기

C# WPF

[C# WPF] 단위변환기

미터와 야드, 킬로그램과 파운드 등 서로 다른 단위로 헷갈릴 때가 있습니다.

이때 서로 단위를 변환해주는 프로그램을 만들고자 합니다.

UI는 표준과학연구원의 단위변환 사이트를 참조하지요~ http://www.kriss.re.kr/standard/view.do?pg=unit_program  

프로그램의 실행 모습은 다음과 같습니다.


Xaml 파일을 보겠습니다.

크게 보면,

 <Window>

       <StackPanel>

              <TextBlock/>

              <Grid>

<TextBlock/>

<TextBox/>

      </Grid>

    </StackPanel>

    <StackPanel>

            .....

    </StackPanel>

</Window>

의 구조입니다.

<Window x:Class="UnitConverter.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="단위변환기 V 0.1 by Beeeye Dmu" Height="350" Width="655">

    <StackPanel>

        <TextBlock Margin="10" FontSize="14" Foreground="OrangeRed" FontWeight="Bold">표준길이단위 변환</TextBlock>

        <Grid Margin="5">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="75"/>

                <ColumnDefinition Width="75"/>

                <ColumnDefinition Width="75"/>

                <ColumnDefinition Width="75"/>

                <ColumnDefinition Width="75"/>

                <ColumnDefinition Width="75"/>

                <ColumnDefinition Width="170"/>

            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>

                <RowDefinition/>

                <RowDefinition/>

            </Grid.RowDefinitions>


            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="3" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="4" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="5" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="6" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="7" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="7" HorizontalAlignment="Right"  Stretch="Fill" Y2="60"></Line>


            <Line Stroke="OrangeRed" Grid.Row="0" Grid.ColumnSpan="7" VerticalAlignment="Top"  Stretch="Fill" X2="600"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.ColumnSpan="7" VerticalAlignment="Bottom" Stretch="Fill" X2="600"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="1" Grid.ColumnSpan="7" VerticalAlignment="Bottom" Stretch="Fill" X2="600"></Line>


            <TextBlock Margin="0,5,0,5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0">meters</TextBlock>

            <TextBlock Margin="0,5,0,5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="1">inches</TextBlock>

            <TextBlock Margin="0,5,0,5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="2">feet</TextBlock>

            <TextBlock Margin="0,5,0,5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="3">yards</TextBlock>

            <TextBlock Margin="0,5,0,5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="4">miles</TextBlock>

            <TextBlock Margin="0,5,0,5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="5">자</TextBlock>

            <TextBlock Margin="0,5,0,5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="6" Grid.ColumnSpan="2">단위변환</TextBlock>


            <TextBox x:Name="txtMeter" HorizontalContentAlignment="Right" Margin="5" Grid.Row="1" Grid.Column="0"></TextBox>

            <TextBox x:Name="txtInch" HorizontalContentAlignment="Right" Margin="5" Grid.Row="1" Grid.Column="1"></TextBox>

            <TextBox x:Name="txtFeet" HorizontalContentAlignment="Right" Margin="5" Grid.Row="1" Grid.Column="2"></TextBox>

            <TextBox x:Name="txtYard" HorizontalContentAlignment="Right" Margin="5" Grid.Row="1" Grid.Column="3"></TextBox>

            <TextBox x:Name="txtMile" HorizontalContentAlignment="Right" Margin="5" Grid.Row="1" Grid.Column="4"></TextBox>

            <TextBox x:Name="txt자" HorizontalContentAlignment="Right" Margin="5" Grid.Row="1" Grid.Column="5"></TextBox>

            <StackPanel Grid.Row="1" Grid.Column="6" Orientation="Horizontal">

                <Button x:Name="btnInit" Margin="5,5,5,5" Width="50" Click="btnInit_Click">초기화</Button>

                <Button x:Name="btnConv" Margin="0,5,5,5" Width="50" Background="#FFFF6E00" Click="btnConv_Click">변환</Button>

                <Button x:Name="btnStandard" Margin="0,5,0,5" Width="50" Background="#FF00B9FF" Click="btnStandard_Click">기준</Button>

            </StackPanel>

        </Grid>

      

        <TextBlock Margin="10" FontSize="14" Foreground="OrangeRed" FontWeight="Bold">표준질량단위 변환</TextBlock>        

        <Grid Margin="5">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="64"/>

                <ColumnDefinition Width="64"/>

                <ColumnDefinition Width="64"/>

                <ColumnDefinition Width="64"/>

                <ColumnDefinition Width="64"/>

                <ColumnDefinition Width="64"/>

                <ColumnDefinition Width="64"/>

                <ColumnDefinition Width="170"/>                

            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>

                <RowDefinition/>

                <RowDefinition/>

            </Grid.RowDefinitions>


            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="3" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="4" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="5" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="6" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="7" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="8" HorizontalAlignment="Left"  Stretch="Fill" Y2="60"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.RowSpan="2" Grid.Column="8" HorizontalAlignment="Right"  Stretch="Fill" Y2="60"></Line>


            <Line Stroke="OrangeRed" Grid.Row="0" Grid.ColumnSpan="8" VerticalAlignment="Top"  Stretch="Fill" X2="600"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="0" Grid.ColumnSpan="8" VerticalAlignment="Bottom" Stretch="Fill" X2="600" Margin="0,0,0,33" Grid.RowSpan="2"></Line>

            <Line Stroke="LightSteelBlue" Grid.Row="1" Grid.ColumnSpan="8" VerticalAlignment="Bottom" Stretch="Fill" X2="600" Margin="0,0,0,-1"></Line>


            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0">kg</TextBlock>

            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="1">ounce</TextBlock>

            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="2">pounds</TextBlock>

            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="3">근</TextBlock>

            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="4">관</TextBlock>

            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="5">돈</TextBlock>

            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="6">tons</TextBlock>

            <TextBlock Margin="5" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="7">단위변환</TextBlock>


            <TextBox x:Name="txtKg" HorizontalContentAlignment="Right" Margin="5,4.52,5,5" Grid.Row="1" Grid.Column="0"></TextBox>

            <TextBox x:Name="txtOunce" HorizontalContentAlignment="Right" Margin="5,4.52,5,5" Grid.Row="1" Grid.Column="1"></TextBox>

            <TextBox x:Name="txtPound" HorizontalContentAlignment="Right" Margin="5,4.52,5,5" Grid.Row="1" Grid.Column="2"></TextBox>

            <TextBox x:Name="txt근" HorizontalContentAlignment="Right" Margin="5,4.52,5,5" Grid.Row="1" Grid.Column="3"></TextBox>

            <TextBox x:Name="txt관" HorizontalContentAlignment="Right" Margin="5,4.52,5,5" Grid.Row="1" Grid.Column="4"></TextBox>

            <TextBox x:Name="txt돈" HorizontalContentAlignment="Right" Margin="5,4.52,5,5" Grid.Row="1" Grid.Column="5"></TextBox>

            <TextBox x:Name="txtTons" HorizontalContentAlignment="Right" Margin="5,4.52,5,5" Grid.Row="1" Grid.Column="6"></TextBox>

            <StackPanel Grid.Column="7" Orientation="Horizontal" Margin="0,27,0,0" Grid.RowSpan="2">

                <Button x:Name="wInit" Margin="5,5,5,5" Width="50" Click="wInit_Click">초기화</Button>

                <Button x:Name="wConvert" Margin="0,5,5,5" Width="50" Background="#FFFF6E00" Click="wConv_Click">변환</Button>

                <Button x:Name="wStandard" Margin="0,5,0,5" Width="50" Background="#FF00B9FF" Click="wStandard_Click">기준</Button>

            </StackPanel>

        </Grid>

    </StackPanel>

</Window>


다음은 소스코드를 보겠습니다.


        private void btnInit_Click(object sender, RoutedEventArgs e)

        {

            txtFeet.Text = "";

            txtInch.Text = "";

            txtMeter.Text = "";

            txtMile.Text = "";

            txtYard.Text = "";

            txt자.Text = "";

        }


        private void btnStandard_Click(object sender, RoutedEventArgs e)

        {

            txtMeter.Text = "1";

            txtInch.Text = "39.3700";

            txtFeet.Text = "3.2808";

            txtYard.Text = "1.0936";

            txtMile.Text = "0.0006";

            txt자.Text = "3.3";

        }


        private void btnConv_Click(object sender, RoutedEventArgs e)

        {

            if(txtFeet.Text == "" && txtInch.Text == "" && txtMeter.Text == "" &&

               txtMile.Text == "" && txtYard.Text == "" && txt자.Text == "")

                return;


            if (txtMeter.Text != "")

            {

                txtInch.Text = (double.Parse(txtMeter.Text) * 39.37).ToString();

                txtFeet.Text = (double.Parse(txtMeter.Text) * 3.2808).ToString();

                txtYard.Text = (double.Parse(txtMeter.Text) * 1.0936).ToString();

                txtMile.Text = (double.Parse(txtMeter.Text) * 0.0006).ToString();

                txt자.Text = (double.Parse(txtMeter.Text) * 3.3).ToString();

            } 

            else if(txtInch.Text != "")

            {

                txtMeter.Text = (double.Parse(txtInch.Text) * 0.0254).ToString();

                txtFeet.Text = (double.Parse(txtInch.Text) * 0.0833).ToString();

                txtYard.Text = (double.Parse(txtInch.Text) * 0.0277).ToString();

                txtMile.Text = (double.Parse(txtInch.Text) * 0.00001578).ToString();

                txt자.Text = (double.Parse(txtInch.Text) * 0.08382).ToString();

            }

            else if (txtFeet.Text != "")

            {

                txtMeter.Text = (double.Parse(txtFeet.Text) * 0.3048).ToString();

                txtInch.Text = (double.Parse(txtFeet.Text) * 12).ToString();

                txtYard.Text = (double.Parse(txtFeet.Text) * 0.333333).ToString();

                txtMile.Text = (double.Parse(txtFeet.Text) * 0.000189).ToString();

                txt자.Text = (double.Parse(txtFeet.Text) * 1.00584).ToString();

            }

            else if (txtYard.Text != "")

            {

                txtMeter.Text = (double.Parse(txtYard.Text) * 0.9144).ToString();

                txtInch.Text = (double.Parse(txtYard.Text) * 36).ToString();

                txtFeet.Text = (double.Parse(txtYard.Text) * 3).ToString();

                txtMile.Text = (double.Parse(txtYard.Text) * 0.000568).ToString();

                txt자.Text = (double.Parse(txtYard.Text) * 3.01752).ToString();

            }

            else if (txtMile.Text != "")

            {

                txtMeter.Text = (double.Parse(txtMile.Text) * 1609.344).ToString();

                txtInch.Text = (double.Parse(txtMile.Text) * 63360).ToString();

                txtFeet.Text = (double.Parse(txtMile.Text) * 5280).ToString();

                txtYard.Text = (double.Parse(txtMile.Text) * 1760).ToString();

                txt자.Text = (double.Parse(txtMile.Text) * 5310.8352).ToString();

            }

            else if (txt자.Text != "")

            {

                txtMeter.Text = (double.Parse(txt자.Text) * 0.30303).ToString();

                txtInch.Text = (double.Parse(txt자.Text) * 11.930327).ToString();

                txtFeet.Text = (double.Parse(txt자.Text) * 0.994194).ToString();

                txtYard.Text = (double.Parse(txt자.Text) * 0.331398).ToString();

                txtMile.Text = (double.Parse(txt자.Text) * 0.00018829).ToString();

            }

        }

위의 소스는 표준길이단위 변환을 위한 부분입니다.

"기준"은 meters를 1로 했을 때 나머지 단위가 어떤 값인지를 보여줍니다. 이 값을 이용하여 상호 변환을 할 수 있습니다. 사용할 때는 6개의 단위 중 하나에 값을 넣고 "변환" 단추를 누르면 계산이 됩니다.

"초기화" 버튼은 모든 TextBox 를 비워줍니다.


이렇게 if~ else if 문을 사용하게 되면 코드가 굉장히 길어지게 됩니다. 각 단위변환을 일일히 코드에 넣어 주어야 합니다. 그래서 이런 경우에는 LUT(Look up Table)을 사용하는게 효율적입니다. 다음은 표준질량단위 변환을 수행하기 위해 LUT를 사용하는 방법입니다.


우선 단위 간의 변환 관계를 엑셀파일에서 계산합니다.

예를 들어 1kg은 2.2046 파운드 라는 걸 알고 있으면, 거꾸로 1 파운드는 1/2.2046 = 0.4536 이 되는 식이지요. 이를 엑셀 식으로 간단히 만들고 Visulal Studio 에 복사해서 2차원 배열로 사용하는 겁니다. 그러면 모든 단위간의 변환 상수를 배열에 저장하고 곱해줌으로써 변환이 됩니다.

이를 코드로 보면 다음과 같습니다.

// 표준질량단위변환표: from Excel

        double[,] wTable = new double [7,7] { {1, 35.2739, 2.2046, 1.6665, 0.2666, 266.6065, 0.001},

             {0.0283, 1, 0.0625, 0.0472, 0.0076, 7.5582, 0.000028},

             {0.453597024, 16.00013608, 1, 0.755919441, 0.120928967, 120.9319151, 0.000453597},

             {0.600060006, 21.16645665, 1.322892289, 1, 0.159975998, 159.979898, 0.00060006},

             {3.750937734, 132.3102026, 8.269317329, 6.250937734, 1, 1000.024381, 0.003750938},

             {0.003750846, 0.132306977, 0.008269116, 0.006250785, 0.000999976, 1, 3.75085E-06},

             {1000, 35273.9, 2204.6, 1666.5, 266.6, 266606.5, 1} };


숫자는 복잡하지만 엑셀이 계산해 주는 거니까 복사해서 사용하면 됩니다.

                                           

        private void wConv_Click(object sender, RoutedEventArgs e)

        {

            if (txtKg.Text == "" && txtOunce.Text == "" && txtPound.Text == "" &&

                txt근.Text == "" && txt관.Text == "" && txt돈.Text == "" && txtTons.Text == "")

                return;

            

            int index;

            double value;

            double[] w = new double[7];


            if (txtKg.Text != "") { index = 0; value = double.Parse(txtKg.Text); }

            else if (txtOunce.Text != "") { index = 1; value = double.Parse(txtOunce.Text); }

            else if (txtPound.Text != "") { index = 2; value = double.Parse(txtPound.Text); }

            else if (txt근.Text != "") { index = 3; value = double.Parse(txt근.Text); }

            else if (txt관.Text != "") { index = 4; value = double.Parse(txt관.Text); }

            else if (txt돈.Text != "") { index = 5; value = double.Parse(txt돈.Text); }

            else { index = 6; value = double.Parse(txtTons.Text); }


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

                w[i] = value*wTable[index,i];


            txtKg.Text = string.Format("{0:F4}", w[0]);

            txtOunce.Text = string.Format("{0:F4}", w[1]);

            txtPound.Text = string.Format("{0:F4}", w[2]);

            txt근.Text = string.Format("{0:F4}", w[3]);

            txt관.Text = string.Format("{0:F4}", w[4]);

            txt돈.Text = string.Format("{0:F4}", w[5]);

            txtTons.Text = string.Format("{0:F4}", w[6]);

        }

    }

}


이렇게 되면 변환하는 코드가 위와 같이 간단하게 만들어 집니다. 파란색 부분을 보면 얼마나 간단히 코딩이 되는지 알 수 있습니다. 

"초기화"와 "기준" 버튼은 다음과 같습니다.


        private void wStandard_Click(object sender, RoutedEventArgs e)

        {

            txtKg.Text = "1";

            txtOunce.Text = "35.2739";

            txtPound.Text = "2.2046";

            txt근.Text = "1.6665";

            txt관.Text = "0.2666";

            txt돈.Text = "266.6065";

            txtTons.Text = "0.001";   

        }


        private void wInit_Click(object sender, RoutedEventArgs e)

        {

            txtKg.Text = "";

            txtOunce.Text = "";

            txtPound.Text = "";

            txt근.Text = "";

            txt관.Text = "";

            txt돈.Text = "";

            txtTons.Text = "";            

        }


DrBeeEye Dmu







'C# WPF' 카테고리의 다른 글

Stopwatch 사용법  (0) 2015.11.18
[WPF] 시계가 나오는 계산기  (0) 2015.10.28
Chart control in WPF  (0) 2015.06.04
[C# WPF]Matching Game in WPF, WPF 매칭게임  (1) 2014.11.26
[C# WPF] Image Button  (0) 2014.09.10