치지직 방송을 대기하다가 방송이 켜졌을 때

자동으로 브라우저를 열어 해당 방송을 켜주는 프로그램을 만들어 테스트를 해보던 도중

아래와 같은 에러에 부딪혔다

막 on된 방송에 들어갈 때 이따금 볼 수 있는 에러

정확히는 프로그램상의 에러는 아니고 치지직에서 막 켜진 방송들이 이따금 에러를 뱉어내다 잠시 후 정상 송출되는 에러다.

문제는 그냥 api를 체크해서 방송의 status가 바뀌었을 때 브라우저를 켜주는 동작만 했더니

위와같은 에러가 뜨면 수동으로 새로고침이라도 해줘야 한다는 점이다.

 

그래서 어떤 부분의 문제인지 테스트를 좀 해봤다. 일단 영상 자체를 불러오지 못하는 문제인가 싶어

방송의 status값이 바뀐 후에도 해당 채널 id값의 media hls값을 제대로 받아오는지 확인한 후

정상적으로 받아올 때 브라우저를 켜주는 식으로 수정하여 실행을 시켜봤다.

 

테스트 실행을 해보니 에러가 날 상황엔 hls 체크를 지속적으로 하다가 정상적인 상태일 때 잘 켜지는 듯 했는데,

오늘 새로 테스트 해보니 다시 에러상태일 때 창이 켜지는 상황이 확인되어 수정을 들어갔다.

 

live-detail 상에 hls주소가 업데이트 된 직후 시간을 주지 않고 바로 창이 켜져서 생긴 문제일 수도 있으나,

그 부분까진 아직 테스트를 해보지 못했다. 위에 말했듯 치지직 상 이따금 생기는 에러라 원할때마다 문제 상황을 재현해보지 못하고 있기 때문

 

일단 해당 에러가 난 페이지를 정상적으로 방송이 송출중인 페이지와 엘리먼트를 비교해보니 

에러상황
정상동작

저렇게 표시해둔 부분에서 차이가 발견되었다. 정상 송출 중에는 src 값을 받아오고 있는 듯 하다. 그래서 해당 값이 어디에서 업데이트 되고 있는지 디버깅 해보았으나..

 

이쪽은 보고있어도 잘 모르것다..

 

일단 이 부분은 놔두고 차선책으로 파이썬에 Selenium을 사용해서 해당 엘리먼트의 src 속성 값을 읽고, 값이 있는지 여부를 확인하는 방법을 취해보거나, 아니면 해당 에러 상황에서 live-detail api 창을 한번 실행시켜서 정보값을 받아온 뒤 해당 값과 이후 정상 송출시의 값에 어떤 차이가 있는지 한번 비교를 해보는 것도 좋을 것 같다.

 

전에 수동으로 live-detail 을 켜서 비교해본 적이 있긴 하지만 그때는 수동이라 속도가 늦기도 했고 문자 비교로 조금만 확인 해봤던거라 확실하지 않다.

 


에러 상황에서의 live-detail 값을 받아와봤다.

같은 값이 나오는 부분은 제외하고 livePlaybackJson 내부의 값에 차이가 확실히 보인다.

에러상황

 

정상

그런데 이미 다르게 나올것은 예상 하던 부분이기도 하다. 기존에 에러상황을 체크하기 위해 mediaID : HLS의 path값이 있는지 확인하는 로직이 있었고 에러상황의 로그 확인중에 이미 이 값이 없다고 여러번 띄웠던 적이 있었기 때문.

문제는 hls의 path 값까지 정상적으로 존재함을 확인 한 후에 열렸던 창에서도 에러가 나왔던 적이 한번 있었는데

그 상황을 다시 재현해보지 못하면 쉽게 알기 어려울 듯 하다.

같은 창의 브라우저 내에서 짧은 시간 간격으로 새 탭에 열리면서 무언가 꼬였을 가능성도 존재하지만 확실한 부분은 없는 상태

사전의 체크로 정확한 구분이 어려우면 그냥 후속적인 체크를 추가하는게 좋긴 하겠다만 일단 테스트 가능한 부분까진 해볼생각

반응형

'IT > buglog' 카테고리의 다른 글

[Unity] 애니메이션 동작 문제..  (0) 2025.03.16

점프 애니메이션 동작에 미묘한 이상 동작이 자꾸 생겨서 문제를 살펴보니 두가지 정도의 문제가 확인 됨

 

우선 하나는 Add.Force로 플레이어를 움직여 주는 현 상태에서

오브젝트가 땅에 착지하는 순간 바로 다시 점프를 수행 했을 때

플레이어의 velocity.y의 값이 즉각적으로 증가하지 않으면서 생기는 문제

정상 동작시 로그
비 정상 동작시 로그

문제는 Add.Force로 움직이는 오브젝트가 관성에 영향을 받아서인 것으로 추정된다.

해결해주기 위해 Add.Force로 값을 주기 직전 기존의 velocity의 값을 0으로 초기화 시켜주는 작업을 추가했다.

...
// 관성 초기화를 위해 움직임 강제 초기화
rb.velocity = Vector3.zero;
// Rigidbody에 힘 적용
rb.AddForce(launchForce, ForceMode.Impulse);
...

일단은 정상 동작 하는 것으로 보임

 


두 번째 문제로는

점프에 대해 settrigger 해주는 부분에 뭔가 이상한 동작을 확인

 

코드 동작 상에서 Settigger는 한번만 시켜주고 실제로 로그 출력 상에서도

Settigger 부분은 한번만 동작 하는게 확인 되었는데

 

애니메이션이 간헐적으로 이상하게 동작하는 때에만 trigger의 bool 값을

GetBool로 확인해보니 true의 값이 연속적으로 나온다

정상 동작일때 (1이 Settigger 동작시 출력되고 True가 Getbool로 가져온 trigger의 상태값이다)
비 정상 동작 ( 1이 한번만 출력된걸 보면 Settrigger는 한번만 호출된 것이 맞는데 trigger의 상태값은 바로 꺼지지 않고 true로 지속된 것이 확인된다)

 

아래처럼 동작 순서를 조정해서 다음 프레임에도 GetBool로 tigger의 값이 true면 로그값이 출력하게 해보니

문제가 생기는 경우에만 로그가 나오는걸 봐선 정상 동작 시 trigger의 값은 첫 프레임에만 켜진 후

다음 프레임엔 false로 꺼지는게 맞는 듯 한데 이게 바로 꺼지지 않아서 생기는 문제인 듯 하다.

 

Update()
{
	...
    if(animator.GetBool("doJump")
    {
    	Debug.Log("test");
    }
    if( .. )
    {
    	animator.SetTrigger("doJump");
    }
    ...
}

 

 

근본적인 해결책이라 보긴 어렵지만 아래와 같이 해서 고쳐봤다. 일단은 문제없이 동작 하는 듯 한데 경과를 더 지켜봐야 할 듯

if (anim.GetBool("doJump"))
{
    anim.ResetTrigger("doJump"); //trigger 초기화
    anim.Play("Jump", 0, 0f); //Jump 애니메이션 강제 실행
}

 

반응형

'IT > buglog' 카테고리의 다른 글

치지직 방송 처음 시작 시 에러  (0) 2025.04.27

치지직의 다시보기를 다운받는 용으로 기존의 명령어를 잘 사용하다가

ffmpeg -ss $starttime -to $endtime -i $URL -c copy $outputFileName

(위와 같은 형태가 기본)

 

근래에 다시보기가 라이브가 끝난 후 바로 업로드 되는 식으로 바뀌면서

m3u8을 읽어오는 방식에 변화가 생긴것인지

기존의 방식으로는 정상 동작을 안하는 상황이 생겼다

 

정확히는 원래의 다시보기 영상 방식

 - 영상을 인코딩 다 해서 올라오는 방식 (거의 영상 길이만큼의 시간이 지난 후에 올라옴)

에서

 - 영상을 인코딩 하는동안 다른 형식으로 다시보기 영상을 송출해준 뒤

   인코딩이 끝나면 해당 영상을 대체하는 방식 (영상이 바로 올라옴)

로 바뀌었다는 느낌인데

저기서 인코딩이 끝나서 대체되기 전까지의 영상에 대해선 기존의 명령어가 

정상적으로 먹히지 않는것이다.

 

이를 해결하기 위해 열심히 찾아봤지만 해결책은 간단했다.

명령어를 아래와 같이 수정해주면 끝이다.

ffmpeg -i $URL -ss $starttime -to $endtime -c copy $outputFileName

 

좀 살펴보다보니 전체 m3u8을 읽어온 뒤 이후 특정 지점을 잘라내는 기존 방식으론 오류가 생기고

m3u8을 읽어오다가 특정 지점에 도달했을 때 영상을 뽑아내는 방식으론 가능했던 것.

그 방법이 위처럼 -i의 순서를 바꿔 ffmpeg의 동작 순서를 조금 바꿔주는 것

영상이 연속적인 정보를 띄고있지 않으면 뭔가 정상 처리되지 않는건가? 아무튼

 

-----------------------------------------------------------------------------------------------------------------------

 

위에까지 고쳐서 잘 쓰던 와중 또 새로운 문제에 직면했다.

치지직 영상에 연령제한이 걸려있을 경우 인증정보를 전달해야 하는데

ffmpeg의 -header를 아무리 써도 제대로 동작을 안하는 것.

(물론 제대로 된 방법을 못찾아서 못한것일 수도 있다)

 

결국 차선책으로 발견한 방법이 yt-dlp의 --cookies 명령어를 쓰는 것이다.

물론 yt-dlp에도 --download-sections 나 --postprocessor-args 같은 영상을 잘라서 다운받는

명령어들이 존재하고 그냥 이거 써서 하면 되는거 아닌가? 싶지만

정확히 연령제한이 걸려있고, 위에서 문제되었던 막 라이브가 끝나 인코딩 되지 않은 영상의 경우

yt-dlp의 두 명령어로는 내가 명령어를 잘못 쓴 것인진 몰라도 정상적으로 동작하지 않았다.

 

그래서 어떤 방식으로 쓰느냐 하면 우선 치지직 메인에서 쿠키를 얻어낸다.

크롬 확장프로그램 EditthisCookies 같은걸 사용해 Netscape 형식으로 쿠키를 추출한다.

이후 쿠키 파일을 yt-dlp에 불러와서 해당 영상의 m3u8링크를 인증된 형태로 얻어온다.

 

yt-dlp --cookies cookie.txt -g URL

 

출력된 링크로

curl.exe -i "m3u8 URL"

 

를 해봐서 HTTP 200 ok가 나오면 정상적으로 인증이 되는 것인 듯 하다.

 

이후 이 링크를 가지고 위에서 썻던

ffmpeg -i $URL -ss $starttime -to $endtime -c copy $outputFileName

 

를 다시 해주면 정상적으로 동작하는 것을 확인할 수 있다.

반응형

이전에 FFMPEG를 이용해 URL을 받아서 미리 영상을 잘라낸 뒤

원하는 부분만 다운받는 방법을 찾아봤었는데

유튜브의 경우는 조금 더 복잡해서 따로 기록해둔다

 

우선 이전에 사용했던 yt-dlp를 이용해 원하는 유튜브 영상의 정보를 가져온다

yt-dlp -g [영상 링크]

 

그러면 주소값이 두개가 출력되는걸 볼 수 있다

예시

왜 두개인가 하면 영상파일과 음성파일이 분리되어 있기 때문이다

위에가 영상 링크이고 아래가 음성 링크이다

 

이보다 더 자세하게 링크를 가져오고 싶으면 아래의 명령어를 쓴다

yt-dlp -F [영상 링크]

 

그러면 해당 영상의 각 해상도별 영상 파일의 ID값을 포함한 정보 등이 나온다

예시2

audio only와 video only에서 원하는 해상도와 비트레이트를 찾아 왼쪽의 ID 값을 확인한 뒤

아래처럼 입력해주면 원하는 화질과 음질로 다운받을 수 있다.

yt-dlp -f [ID]+[ID] [URL]

#예시 1280x720 30fpds mp4 영상과 129kbps 음성을 합친 뒤 출력
yt-dlp -f 136+140 https://youtu.be/JL_GJShS4fU?si=jYcpT303JjgxFOca

 

하지만 내가 원하는건 해당 링크를 가져오는것이니 아래처럼 입력해준다.

yt-dlp -f [ID]+[ID] [URL] --get-url

 

그 후 얻어낸 링크로 ffmpeg에 적용하기 전에 문제가 있다.

링크에 보면 특수문자 &가 여러번 들어간게 보이는데 링크에 이 문자가 포함되어 있으면

실행중 에러를 뱉어낸다.

그러니 미리 &를 찾아 모두 "&"로 바꿔준다.

vscode같이 찾아서 모두변환이 있는 프로그램을 쓰면 편하다

 

이제 ffmpeg에서 아래와 같이 써준다.

ffmpeg -ss [시작 시간] -to [끝나는 시간] -i [영상 링크] -ss [시작 시간] -to [끝나는 시간] -i [음성 링크] -c copy -map 0:v:0 -map 1:a:0 output.mp4

 

 

각 링크의 파일을 잘라낸 뒤 -c copy로 재인코딩 없이 복사 한 후

-map으로 첫번째 파일의 비디오 스트림과 두번째 파일의 오디오 스트림을 출력파일에 매핑하는 것이다.

 

반응형

짤막한 클립영상을 만들려고 다시보기 영상들을 통째로 다운받고 잘라서 편집하다보니

하나에 20~30GB는 우습게 넘기는 크기 영상들을 다운받아서 작업을 했는데

이게 하드 수명에도 그닥 좋지 않을거같고 해서 다른 방법을 찾아봤다.

 

기존에 영상을 잘라내는데에 쓰던 FFMPEG 명령어를 조금 손봐서 Input 영상을 url로 대체하면

가능하지 않을까 시도했다.

 

#$starttime부터 $endtime까지의 영상으로 잘라내는 명령어
ffmpeg -i video.mp4 -ss $starttime -to $endtime -vcodec copy -acodec copy output.mp4

 

 

#Input video를 다운받을 영상의 URL로 바꿔줌
ffmpeg -i [URL] -ss $starttime -to $endtime -vcodec copy -acodec copy output.mp4

 

하지만 이렇게 바꿔서 시도해보니 아래처럼 0 frame에서 작업이 멈춘 상태로 진행되지 않았다.

이 상태에서 멈춰있다

 

그래서 다른방법이 있을까 하고 찾아봤지만 결과적으론 그냥 명령어 순서의 문제였다.

아래와 같이 해주면 정상 작동한다.

ffmpeg -ss $starttime -to $endtime -i [URL] -c copy output.mp4

 


왜 그냥 갖고있던 영상을 다룰때와 URL로 받아와서 다룰때 명령어 순서에 차이가 생기는지는 모르겠다.

 

 


치지직에서 해당 다시보기 영상의 URL을 가져오는 방법

 

해당 영상에 들어가 f12로 개발자모드를 키고 Network탭에서 m3u8을 검색하면 아래와 같이 나온다

결과들을 눌러보면 위처럼 key=가 들어간 값을 가리키는게 있다

거기서 preview로 들어가면

이렇게 BaseURL과 m3u8 링크를 얻을 수 있다.

 

이 중 BaseURL을 써야 정상작동 한다.

 

---

 

이 방법이 복잡하면 그냥 yt-dlp를 사용하는 방법도 있다.

https://github.com/yt-dlp/yt-dlp

 

GitHub - yt-dlp/yt-dlp: A feature-rich command-line audio/video downloader

A feature-rich command-line audio/video downloader - yt-dlp/yt-dlp

github.com

링크에 들어가서

윈도우 기준 yt-dlp.exe를 다운받아 ffmpeg와 같은 폴더에 넣은 뒤 명령 프롬프트에서 해당 폴더로 이동하고

yt-dlp -g [영상링크]

위 명령어를 쓰면 쉽게 BaseURL을 받아올 수 있다.

예시

 

반응형

비디오 효과 중 자르기 효과를 사용한다.

 

자르기

우선 트랙에 색을 입힌 자막과 그렇지 않은 자막을 겹치게 만들어 준다.

색을 입힌 자막이 위에 가도록 하면 이렇게 색을 입힌 자막만 보인다

색을 입힌 자막에 자르기 효과를 넣고 자르기 효과 중 오른쪽을 100%로 설정한다.

이미지와 같이 설정

그 후 노래에 맞춰 키프레임마다 수치를 조절해 주면 된다.

예를들어 위에처럼 가나다라마바사 라는 가사에서 가나다까지 말했다면

그곳에 키프레임을 두고 수치를 조절해 가나다까지 색이 입혀지도록 조절한다.

 

주의할 부분은 자르기 효과가 효과를 입힌 자막 기준이 아니라

화면 전체를 기준으로 100~0%를 나누는 듯 하기에

자막 위치를 오른쪽으로 이동시키면 100%에서 바로 색이 입혀지지 않을 수 있다.

반응형

한번에 여러개의 반복되는 파일 이름을 바꾸고자 할 때

윈도우 파워쉘에서 명령어로 수행 가능하다.

 

파일들이 있는 폴더에서 파워쉘을 킨 후

 

해당 폴더에서 shift+우클릭을 하면 여기에 PowerShell 창 열기가 있다

 

 

Get-Childitem "바꿀 대상" | ForEach-Object {Rename-Item $_.FullName -NewName($_.Name -replace "원래 이름", "바꿀 이름")}

을 하면 바뀐다.

 

예를 들어

이렇게 하면 폴더 내의 모든 .txt파일에서 aaaa로 된 단어를 bbbb로 바꾼다.

결과물..

 

좀 더 세부적으로 바꾸고 싶으면 정규식 등을 이용해도 좋다.

 

만약 폴더 내의 .txt파일을 이름이 뭐든 상관없이 test0부터 숫자가 증가하는 식으로 만들고 싶다면

이런식으로도 쓸 수 있다.

(정규식에 .+가 아니라 \w+를 쓰면 글자 하나하나를 test.txt로 바꿔버린다..)

결과물..

 

반응형


ProgressBar는 작업 진행률을 사용자에게 보여주거나 할 때 쓰이는 도구이다.

흔히 로딩바라고 부르는것과 비슷하다.


만들어본 동작은 간단하다. 아래 그림 1,2,3과 같이

버튼을 누르면 ProgressBar가 0에서 100까지 진행한 뒤 진행완료 메시지를 출력하는것.


<그림 1>


<그림 2>


<그림 3>


ProgressBar 도구가 이미 만들어져 있기에 사용법은 간단하다.

도구 상자의 ProgressBar를 찾아 넣기만 하면 끝이다.

처음 생성시키면 속성의 Max값과 Min값은 각각 100과 0으로 설정되어 있다.

만약 위처럼 겉모양만 해보는게 아닌 실제 작업진행률을 표시할 땐

이 Max값을 전체 작업량으로 설정하면 될 것이다.


그 외에 눈여겨 볼 속성으론 Step과 Value, Style정도가 있다.


Step 속성은 PerformStep() 메서드를 호출할 때 표시줄의 현재 위치를 증분시킬 크기를 설정할 수 있는 속성이다.

예를들어 Step값이 1이면 Max가 100 Min이 0일 때 작업이 100번 일어나야 표시줄이 다 채워지는 것.

Step속성을 지정하고 PerformStep()메서드로 진행하는 방법도 있지만

Increment(Step값)를 이용해서 진행하는 방법도 있다.


1
2
3
4
                //Increment이용
                this.progressBar1.Increment(1);
                //Step, PerformStep 이용
                this.progressBar1.PerformStep();
cs

<코드 1>


Step의 크기가 1일 때 <코드 1>의 두 코드는 같게 동작한다.


Value 에는 표시줄의 현재 진행 값이 들어간다.


Style 속성으론 표시줄의 스타일을 지정할 수 있다. 

Blocks, Continuous, Marquee 로 3가지 스타일이 있는데 OS에 따라 다른경우도 있다.

Blocks와 Continuous는 똑같이 연속적으로 증가하는 형태지만

Blocks의 경우 XP 이전의 OS에서는 블록을 쌓아가는 형태의 표시줄로 보여진다.


<그림 4 : 구버전 OS의 Blocks 스타일>


<그림 5 : Marquee 스타일>


아래는 위 그림1,2,3을 구현한 코드다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        private void button1_Click(object sender, EventArgs e)
        {
            //backgroundWorker1.RunWorkerAsync();
            
            for (int i = 0; i < 100; i++)
            {
                //this.progressBar1.Increment(1);
                this.progressBar1.PerformStep();
                this.label1.Text = progressBar1.Value.ToString() + "%";
                Update();
                //this.label1.Refresh();
                Thread.Sleep(100);
            }
            
            if (progressBar1.Value == 100)
            {
                MessageBox.Show("진행완료");
            }
            
        }
cs

<코드 2>


동작을 구현하던 중 한가지 문제를 겪었었는데

바로 ProgressBar가 진행하는 동안 진행률을 표시해주기 위해 label.Text에 값을 넣어주는 코드가

정상적으로 동작하지 않는 문제였다.


코드 자체는 동작을 했지만 프로그래스바가 진행 완료될 때 까지 실시간으로 화면에 출력되지는 않는 문제였는데

혹시 스레드가 자식객체인 표시줄을 진행시키는 일에 할당되어 label값이 변경되어도 부모객체인 Form을 update시키질

못하는게 아닐까 생각되어 찾아보니 내부에서 따로 Update문을 추가하는 것으로 해결할 수 있었다.

<코드 2>의 10번 줄을 보면 Update문을 추가한 것을 볼 수있다. 

Update이외에도 11번 줄로처럼 Label을 Refresh시켜주는 것으로도 대체 가능했다.


Update나 Refresh말고도 BackgroundWorker를 이용하는 방법도 있다는것 같은데

몇번 시도해봤지만 어째선지 실패하여 일단 보류시켜뒀다.

반응형


스크롤바는 세로 스크롤바(VScrollBar)와 가로 스크롤바(HScrollBar) 두개가 있다.

이 중 HScrollBar를 이용해 RGB값을 변경하도록 해본다.


[그림 1]


먼저 Form을 생성해준 뒤 도구상자에서 HScrollBar을 가져와 [그림 1]처럼 놔준다.

3개의 스크롤바는 각각 R, G, B값의 0부터 255까지 수치를 맡게할것이다.


RGB값의 변화를 확인하기 위해 임시로 Label을 하나 생성한 뒤

label의 BackColor 값을 변경시키게 한다.


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
        private void ChangeColor()
        {
            int r = this.hScrollBar1.Value;
            int g = this.hScrollBar2.Value;
            int b = this.hScrollBar3.Value;
 
            this.label1.BackColor = Color.FromArgb(r, g, b);
            this.label1.Text = String.Format("RGB 색상값 : RGB({0}, {1}, {2})", r, g, b);
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            this.label1.BackColor = Color.Black;
        }
 
        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            ChangeColor();
        }
 
        private void hScrollBar2_Scroll(object sender, ScrollEventArgs e)
        {
            ChangeColor();
        }
 
        private void hScrollBar3_Scroll(object sender, ScrollEventArgs e)
        {
            ChangeColor();
        }
cs

[코드 1]


RGB값은 0부터 255까지밖에 값이 들어가지 않기때문에 ScrollBar의 Maximum이나 Minimum속성값을

0에서 255범위 밖의 값으로 지정해도 스크롤바를 해당 수치 넘어서까지 움직이면 오류가 뜬다.

[코드 1]처럼 스크롤 상자를 이동할 때 동작하는 Scroll이벤트를 이용해 이동시마다 RGB값 변경을 보여줄 수 있다.


하지만 제대로 동작하기 위해선 ScrollBar의 LargeChange속성을 1로 변경시켜줘야 한다.

LargeChange속성은 스크롤 막대를 클릭하거나 <Page UP> 또는 <Page Down> 키를 누를 때 스크롤 상자 위치가 변경되는 정도를 설정해두는 속성으로 기본값으로는 10이 설정되어있다.

그런데 이 속성값을 10으로 둘 경우 스크롤 상자를 끝까지 옮겨도 설정해둔 Maximum값까지 올라가지 않는 문제가 있다.

어째서 LargeChange속성이 Maximum속성 값에 직접적 영향을 끼치는지 파악하지는 못했다.


[그림 2]


정상적으로 동작하면 [그림 2]와 같은 모습이 나온다.

반응형

 

RadioButton과 CheckBox 도구(클래스)는 사용자에게 선택지를 줄 때 사용할 수 있다.


[그림 1 : 좌 라디오버튼 우 체크박스]


radiobutton과 checkbox에는 공통적으로 존재하는 이벤트로 CheckedChanged가 있다.

'Checked' 속성의 값이 변경될 때 동작하는 이벤트인데, 

이를 이용해 선택하는 동작이 있었을 때를 트리거로 다른 동작을 구현할 수 있다.


1
2
3
4
5
6
7
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
    if (sender == this.radioButton1)
    {
        //동작
    }
}
cs

[코드 1]


1
2
3
4
5
6
7
8
9
10
11
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
    if (sender == this.checkBox1)
    {
        //동작
    }
    if (this.checkBox1.Checked == false)
    {
        //동작
    }
}
cs

[코드 2]


[코드 1]의 sender == this.radioButton1 은 this.radioButton1.Checked == true 로도 사용 가능하다.

마찬가지로 [코드 2]의 sender == this.checkBox1 도 this.checkBox1.Checked == true 로 사용 가능하다.


체크박스의 경우 여러개의 체크박스를 ListBox에 넣어 묶음으로 사용 가능하게 만들어둔

CheckedListBox 도구가 따로 존재한다.

Items라는 속성을 가지며 그 안에 체크박스 항목들을 자식 컨트롤로 갖는다.

항목들을 추가하기 위해 속성 창의 Items 프로퍼티 컬랙션을 설정하거나 Designer.cs 또는 초기화 코드에서

checkedListBox1.Items.Add("항목이름"); 처럼 직접 넣을 수 있다.

추가된 항목들은 각자 0번부터 Index값을 갖는다.


[그림 2]


CheckedListBox의 경우 그냥 CheckBox와는 달리 Item을 선택했을때 발생하는 SelectedIndexChanged 이벤트와

Item의 Checked 상태가 변경될 때 발생하는 ItemCheck 이벤트가 있다.


1
2
3
4
5
6
        private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //if(this.checkedListBox1.SelectedIndex != -1){
                this.label1.Text = this.checkedListBox1.SelectedItem.ToString();
            //}
        }
cs

[코드 3]


SelectedIndexChanged 이벤트는 SelectedIndex 값이 변경될 때 발생하는데

아무것도 선택된 항목이 없을 시 SelectedIndex 는 -1값을 갖고있다. 이를 이용해 조건문을 만들 수 있지만

[코드 3]처럼 해도 이벤트 발생을 위해선 일단 SelectedIndex 값이 변경되어야 하기에 동작은 차이가 없다.


1
2
3
4
5
6
7
8
9
10
11
12
13
        private void itemCheck_Changed(object sender, ItemCheckEventArgs e)
        {
            string item = this.checkedListBox1.SelectedItem.ToString();
            this.label1.Text = e.NewValue.ToString();
            if (e.NewValue == CheckState.Checked)
            {
                this.listBox1.Items.Add(item);
            }
            else
            {
                this.listBox1.Items.Remove(item);
            }
        }
cs

[코드 4]


ItemCheck 이벤트에선 e.NewValue로 현재 항목의 Checked 상태를 가져올 수 있다.

상태로는 Checked와 Unchecked 그리고 Indeterminate가 있다.

Checked는 선택된 상태 Unchecked는 선택되지 않은 상태 Indeterminate는 결정되지 않은 상태로


[그림 3 출처 : https://css-tricks.com/indeterminate-checkboxes/]


Indeterminate는 [그림 3]의 Tall Things 같은 경우 사용한다 생각하면 될 듯 하다.


[코드 4]의 5번 라인 처럼 현재 선택된 항목의 체크 상태를 불러와 CheckState를 이용해 비교하여 조건문을 만들 수 있다.

반응형

+ Recent posts