티스토리 뷰

VS-02분반수업

VP02(22-05-13)

choimyeongheon 2022. 5. 17. 00:41

[1]Splash(DB에 RGB값을 저장하거나 불러와 그리드에 색을 칠하는 프로그램)

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace _034_Splash
{
  /// <summary>
  /// MainWindow.xaml에 대한 상호 작용 논리
  /// </summary>
  public partial class MainWindow : Window
  {
    List<Border> borderList;
    DispatcherTimer t = new DispatcherTimer();
    Random r = new Random();
    SqlConnection conn;
    string connStr = @"Data Source = (LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\choi\Desktop\VP02-master (2)\VP02-master\034_Splash\Colors.mdf;Integrated Security = True";

    public MainWindow()
    {
      InitializeComponent();
      borderList = new List<Border>
      {
        bd1, bd2, bd3, bd4, bd5, 
        bd6, bd7, bd8, bd9, bd10,
        bd11, bd12, bd13, bd14, bd15, 
        bd16, bd17, bd18, bd19, bd20
      };
      t.Interval = new TimeSpan(0, 0, 1); // 1초
      t.Tick += T_Tick;
    }

    int index = 0;
    private void T_Tick(object sender, EventArgs e)
    {
      string date = DateTime.Now.ToString("yyyy-MM-dd");
      string time = DateTime.Now.ToString("HH:mm:ss");
      lblDate.Text = date;
      lblTime.Text = time;

      byte[] colors = new byte[20];
      for(int i = 0; i < 20; i++)
      {
        colors[i] = (byte)(r.Next(256));
        borderList[i].Background
          = new SolidColorBrush(
            Color.FromRgb((byte)0, (byte)0, colors[i]));
      }

      string sql = string.Format(
        "INSERT INTO ColorTable VALUES ('{0}', '{1}'",
        date, time);
      for(int i = 0; i < 20; i++)
      {
        sql += string.Format(", {0}", colors[i]);
      }
      sql += ")";
      //MessageBox.Show(sql);

      using(conn = new SqlConnection(connStr))
      using(SqlCommand cmd = new SqlCommand(sql, conn))
      {
        conn.Open();
        cmd.ExecuteNonQuery();
      }

      string s = "";
      s += date + " " + time + " ";
      for (int i = 0; i < 20; i++)
        s += colors[i] + " ";
      lstDB.Items.Add(s);

      // 리스트 박스의 스크롤
      lstDB.SelectedIndex = index++;
      lstDB.ScrollIntoView(lstDB.SelectedItem);
    }

    bool flag = false;
    private void btnRandom_Click(object sender, RoutedEventArgs e)
    {
      if (flag == false)
      {
        t.Start();
        btnRandom.Content = "정지";
        flag = true;
      }
      else
      {
        t.Stop();
        btnRandom.Content = "랜덤 색깔 표시";
        flag= false;
      }

    }

    int id = 0;
    // DB에 저장된 색깔 표시
    private void btnDB_Click(object sender, RoutedEventArgs e)
    {
      lstDB.Items.Clear();

      string sql = "SELECT * FROM ColorTable";
      int[] colors = new int[20];

      using (conn = new SqlConnection(connStr))
      using (SqlCommand cmd = new SqlCommand(sql, conn))
      {
        conn.Open();
        SqlDataReader reader = cmd.ExecuteReader();

        while(reader.Read())
        {
          lblDate.Text = reader["Date"].ToString();
          lblTime.Text = reader["Time"].ToString();
          for(int i=0; i<20; i++)
          {
            colors[i] = int.Parse(reader[i+3].ToString());
          }

          string s = "";
          s += reader["Date"].ToString() + " " 
            + reader["Time"].ToString();
          for(int i=0; i<20; i++)
          {
            s += " " + reader[i + 3].ToString();
          }

          lstDB.Items.Add(s);
          // 스크롤 기능
          lstDB.SelectedIndex = id++;
          lstDB.ScrollIntoView(lstDB.SelectedItem);

          for(int i=0; i<20; i++)
          {
            borderList[i].Background =
              new SolidColorBrush(
                Color.FromRgb((byte)0, (byte)0, (byte)colors[i]));

            // WPF에서 delay 주기
            Dispatcher.Invoke((ThreadStart)(() => { }),
              DispatcherPriority.ApplicationIdle);
            Thread.Sleep(20);  // 0.02 초 delay
          }
        }
      }
    }

    // DB의 내용을 다 지운다
    private void btnReset_Click(object sender, RoutedEventArgs e)
    {
      lstDB.Items.Clear();
      string sql = "DELETE FROM ColorTable";

      using(conn= new SqlConnection(connStr))
      using(SqlCommand cmd = new SqlCommand(sql, conn))
      {
        conn.Open();
        cmd.ExecuteNonQuery();
      }
    }

    private void btnExit_Click(object sender, RoutedEventArgs e)
    {
      Close();
    }
  }
}

전체 코드이다.

using System.Data.SqlClient;
using System.Windows.Threading;

Service-Based-Database 사용을 위해 위의 using 두 개를 선언해준다.

저번시간엔 위와같은 레이아웃을 만들어주었다.

List<Border> borderList;
    DispatcherTimer t = new DispatcherTimer();
    Random r = new Random();
    SqlConnection conn;
    string connStr = @"Data Source = (LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\choi\Desktop\VP02-master (2)\VP02-master\034_Splash\Colors.mdf;Integrated Security = True";

{1}_partial class 안에 Border class타입의 변수들을 저장할 borderList를 선언해준다.

{2}_윈도우폼앱에서 Timer가 WPF에서 DispatcherTimer로 쓰인다. 

        DispatcherTimer클래스타입의 t를 선언해준다.

{3}_Random class r Declare

{4}_현재 VS installer를 통해 설치한 DB를 사용중이므로 Provider는 따로 입력해주지 않고

         LocalDB형식의 MSSQLLocalDB의 문법으로 DB의 주소를 문자열로 저장하여

public MainWindow()
    {
      InitializeComponent();
      borderList = new List<Border>
      {
        bd1, bd2, bd3, bd4, bd5, 
        bd6, bd7, bd8, bd9, bd10,
        bd11, bd12, bd13, bd14, bd15, 
        bd16, bd17, bd18, bd19, bd20
      };
      t.Interval = new TimeSpan(0, 0, 1); // 1초
      t.Tick += T_Tick;
    }
    int index = 0;

선언해준 borderList에 grid의 name을 전부 넣어준 뒤 timespan 으로 t의 인터벌을 1초로 설정해준다.

t.Tick의 eventListener를 T_Tick으로 설정해준뒤 메서드를 생성해준다.

index를 전역변수 0으로 설정해준다.

private void T_Tick(object sender, EventArgs e)
    {
      string date = DateTime.Now.ToString("yyyy-MM-dd");
      string time = DateTime.Now.ToString("HH:mm:ss");
      lblDate.Text = date;
      lblTime.Text = time;

      byte[] colors = new byte[20];
      for(int i = 0; i < 20; i++)
      {
        colors[i] = (byte)(r.Next(256));
        borderList[i].Background
          = new SolidColorBrush(
            Color.FromRgb((byte)0, (byte)0, colors[i]));
      }

      string sql = string.Format(
        "INSERT INTO ColorTable VALUES ('{0}', '{1}'",
        date, time);
      for(int i = 0; i < 20; i++)
      {
        sql += string.Format(", {0}", colors[i]);
      }
      sql += ")";
      //MessageBox.Show(sql);

      using(conn = new SqlConnection(connStr))
      using(SqlCommand cmd = new SqlCommand(sql, conn))
      {
        conn.Open();
        cmd.ExecuteNonQuery();
      }

      string s = "";
      s += date + " " + time + " ";
      for (int i = 0; i < 20; i++)
        s += colors[i] + " ";
      lstDB.Items.Add(s);

      // 리스트 박스의 스크롤
      lstDB.SelectedIndex = index++;
      lstDB.ScrollIntoView(lstDB.SelectedItem);
    }

T_Tick함수의 코드이다.

{1}_date와 time을 sql형식에 맞춰 string타입으로 작성해준 뒤 xaml에서 설정해준 textblock의 text로 설정준다.

{2}_byte타입으로 20칸짜리 colors배열을 선언해준다.

{3}_for문에서 colors[i]에 0~255사이의 정수값을 저장해준다.(byte배열의 범위와 일치함)

{4}_borderList에 저장된 grid들의 배경색을 SolidColorBrush함수를 사용하여 color[i]의 값을 참조하여 칠해준다.

 

string sql = string.Format(
        "INSERT INTO ColorTable VALUES ('{0}', '{1}'",
        date, time);
      for(int i = 0; i < 20; i++)
      {
        sql += string.Format(", {0}", colors[i]);
      }
      sql += ")";

{1}_string 타입의 sql을 SQL문법에 맞추어 작성해준다 (date와 time을 인자로 받도록) - 값을 테이블에 추가해주는 메서드임

{2}_for문을 20번 돌려 string.Format에 {0} = colors[i]를 지정해준다 마지막에 )를 삽입해 sql문을 완성한다.

의문점 : {0}을 더해주면 {0},{1},{0},{0},{0}. . .이 되는건지 

using(conn = new SqlConnection(connStr))
      using(SqlCommand cmd = new SqlCommand(sql, conn))
      {
        conn.Open();
        cmd.ExecuteNonQuery();
      }

using을 사용하여 이 함수 안에서 잠시 사용해준다

(C++의 인라인함수나 lamda식처럼 함수가 끝날 때 heap에서 메모리를 지워주는 것인지)

conn을 설정한 후 conn을 기반으로 comm을 작성하여 executenonquery를 실행해준다.

ExecuteNonQuery함수는 변경된 테이블의 cell속성등을 초기화해주는 query함수임

string s = "";
      s += date + " " + time + " ";
      for (int i = 0; i < 20; i++)
        s += colors[i] + " ";
      lstDB.Items.Add(s);

string타입 s를 만들어 방금 난수를 선언했던 colors의 값들을 뽑아와 저장해준 후 lstDB의 아이템으로 추가해준다.

lstDB.SelectedIndex = index++;
lstDB.ScrollIntoView(lstDB.SelectedItem);
bool flag = false;

{1}_lstDB의 선택값을 index++값으로 설정하여 T_Tick에 의해 계속 값이 추가될 때 가장 마지막에 추가된 값으로 selectedItem을 설정{2}_ScrollIntoView를 마지막 값으로 설정하여 계속 scroll이 마지막값을 트래킹함

{3}_flag를 false로 하여 선언해줌

private void btnRandom_Click(object sender, RoutedEventArgs e)
    {
      if (flag == false)
      {
        t.Start();
        btnRandom.Content = "정지";
        flag = true;
      }
      else
      {
        t.Stop();
        btnRandom.Content = "랜덤 색깔 표시";
        flag= false;
      }

    }
int id = 0;

{1}_만약 랜덤으로 출력 버튼을 눌렀을 때 멈춰있는 상태였다면 버튼의 content를 '정지'로 바꾸고 flag를 true로 해준 뒤 Tick을 실행

{2}_그렇지 않다면 Tick을 멈추고 content를 원래대로 바꾼 뒤 flag를 false로 해줌

{3}_id를 int형 0으로 선언해줌

private void btnDB_Click(object sender, RoutedEventArgs e)
    {
      lstDB.Items.Clear();

      string sql = "SELECT * FROM ColorTable";
      int[] colors = new int[20];

      using (conn = new SqlConnection(connStr))
      using (SqlCommand cmd = new SqlCommand(sql, conn))
      {
        conn.Open();
        SqlDataReader reader = cmd.ExecuteReader();

        while(reader.Read())
        {
          lblDate.Text = reader["Date"].ToString();
          lblTime.Text = reader["Time"].ToString();
          for(int i=0; i<20; i++)
          {
            colors[i] = int.Parse(reader[i+3].ToString());
          }

          string s = "";
          s += reader["Date"].ToString() + " " 
            + reader["Time"].ToString();
          for(int i=0; i<20; i++)
          {
            s += " " + reader[i + 3].ToString();
          }

          lstDB.Items.Add(s);
          // 스크롤 기능
          lstDB.SelectedIndex = id++;
          lstDB.ScrollIntoView(lstDB.SelectedItem);

          for(int i=0; i<20; i++)
          {
            borderList[i].Background =
              new SolidColorBrush(
                Color.FromRgb((byte)0, (byte)0, (byte)colors[i]));

            // WPF에서 delay 주기
            Dispatcher.Invoke((ThreadStart)(() => { }),
              DispatcherPriority.ApplicationIdle);
            Thread.Sleep(20);  // 0.02 초 delay
          }
        }
      }
    }

DB에 저장된 색깔 표시 버튼을 눌렀을 때의 메서드이다.

{1}_현재lstDB에 적혀있는 item들을 clear해준 뒤

{2}_sql에 table값 전체를 불러오는 명령어를 string형태로 저장해준다.

{3}_int형 배열 colors를 만들어 랜덤버튼에서 쓰던 것 처럼 using문을 작성해준 뒤 중괄호를 열어준다.

{4}_connection을 열어준 뒤 reader를 선언해준다.

{5}_Read Value가 true일때 while문이 돌아가도록 선언해준다.

{6}_xaml에서 선언해준 date와 time의 텍스트를 받아오는데 SqlDataReader를 사용하면 대괄호 안의 값을 string으로 받아

       get한다.

{7}_LocalDB table의 1,2,3번째 값은 Id,Date,Time이므로 4번째값부터(i+3) p값을 차례대로 받아와 colors에 넣어준다.

{8}_string type s를 생성해준 뒤 reader로 Date와 Time값을 받아 더해주고 

{9}_reader로 읽어온 테이블의 4~end값 까지의 값을 모두 더해준 뒤(colors[i]의 값를 받아도 된다.) lstDB에 저장해준다.

{10}_id값을 더미로 한 ScrollView를 설정해준다.

{11}_그 다음 borderList에 저장된 border들의 background를 FromRgb함수를 사용하여 칠해주는데

// WPF에서 delay 주기
            Dispatcher.Invoke((ThreadStart)(() => { }),
              DispatcherPriority.ApplicationIdle);
            Thread.Sleep(20);  // 0.02 초 delay

WPF프로젝트의 delay구현부이다.

이를 사용하기 위해 using System.Window.Threading; 을 추가해주어야한다.

자세히는 모르겠지만 멀티스레딩을 해주는 것 같다.

{1}_멀티스레드를 설정함

{2}_Dispatch의 우선순위를 정해주는 것 같음

        현재 ApplicationIdle의 value는 2임 2순위인 것 같고 메인스레드가 휴면상태일 때 진행되는 것 같음 

{3}_Sleep으로 메인스레드를 0.02초동안 휴면상태로 보냄

요약 : Sleep으로 0.02초동안 메인스레드를 재움으로써 ApplicationIdle의 우선순위에 따라 Idle일때 발동하는

          thread delegate를 반환함 여기서 subthread를 시작하는데 내용이 빈칸이므로 delegate는 null을 반환하게되고

          0.02초동안 아무일도 일어나지 않고 null만 반환하다가 메인스레드가 다시 깨어남.

//주관적인 생각입니다...

 

private void btnReset_Click(object sender, RoutedEventArgs e)
    {
      lstDB.Items.Clear();
      string sql = "DELETE FROM ColorTable";

      using(conn= new SqlConnection(connStr))
      using(SqlCommand cmd = new SqlCommand(sql, conn))
      {
        conn.Open();
        cmd.ExecuteNonQuery();
      }
    }

다음은 리셋버튼이다. lstDB의 아이템들을 clear한 상태로 시작한다.

{1}_sql명령어를 delete로 설정해준다.

{2}_위의 버튼들과 마찬가지로 using을 사용하여 conn과 cmd를 설정해준 뒤 중괄호를 열어준다.

{3}_conn을 열고 cmd로 변경사항을 query전송한다.(sql의 내용이 DELETE이고 conn이 sql을 받아 cmd에 넘겼으므로 모두 삭제됨)

 

private void btnExit_Click(object sender, RoutedEventArgs e)
    {
      Close();
    }

마지막 종료버튼은 close함수를 사용하여 window를 닫아주면 된다.

 

감사합니다

 

'VS-02분반수업' 카테고리의 다른 글

VP(22-05-25)  (0) 2022.05.25
VP(22-05-20)  (0) 2022.05.24
VP02(22-05-11)  (0) 2022.05.16
VP(22-05-06)  (0) 2022.05.08
VP(22-05-04)  (0) 2022.05.08
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함