본문 바로가기

Development/Tetris

Python - 테트리스(Tetris) 만들기 (16) - Checkbox

여기까지 잘 따라오신 분들은 Checkbox를 만드는데 전혀 어려움이 없을 것이라 생각됩니다. Checkbox 그림을 넣어서 표현해도 좋지만 간략하게 빈 네모에서 색깔이 찬 네모를 표현하는 것으로 간단하게 만들어 보겠습니다.

 

Checkbox 위치 잡기

python code로 만들면 다음과 같습니다.

class CheckBox:
    _ACTIVATE_COLOR = (127, 255, 127)
    _DEACTIVATE_COLOR = (192, 192, 192)    
    BACKGROUND_COLOR_MAP = {True: _ACTIVATE_COLOR, False: _DEACTIVATE_COLOR}
    LINE_COLOR = (255, 255, 255)

    def __init__(self, x, y, size):
        self.x, self.y, self.size = x, y, size
        self.checkbox_rect = pg.Rect(x, y, size, size)
        self._radius = int(size/4)
        self._line_width = 1
        self._is_checked = False
    
    def update(self, surface):
        if self._is_checked:
            pg.draw.rect(surface, self.BACKGROUND_COLOR_MAP[self._is_checked], self.checkbox_rect, 0, self._radius)
        else:
            pg.draw.rect(surface, self.BACKGROUND_COLOR_MAP[self._is_checked], self.checkbox_rect, self._line_width, self._radius)

    def event_handler(self, event: pg.event.Event):
        if event.type == pg.MOUSEBUTTONDOWN:
            if self.checkbox_rect.collidepoint(event.pos):
                self._is_checked = not self._is_checked

 

그리고 SubsettingDisplay에도 추가해 줍시다.

 

    def __init__(self, width, height):

        ### 생략 ###
        
        self.checkbox_ghost_system = CheckBox(width * self.SYSTEM_LABEL_W, height * self.INPUT_H * 3, height * self.INPUT_H)
        self.checkbox_hold_system = CheckBox(width * self.SYSTEM_LABEL_W, height * self.INPUT_H * 4, height * self.INPUT_H)

    def event_handler(self, event):
        
        ### 생략 ###

        self.checkbox_hold_system.event_handler(event)
        self.checkbox_ghost_system.event_handler(event)

    def update(self):
    
    	### 생략 ###
    
        self.checkbox_ghost_system.update(self.display_surface)
        self.checkbox_hold_system.update(self.display_surface)

 

그러면 다음과 같은 결과를 얻게 됩니다.

 

Checkbox를 만들었지만 디자인적으로는 좋지 않다.

 

이제 디자인적인 요소를 다듬어 봅시다. Line 두께를 Key Mapping의 input과 같게 만들고, 안쪽에 check를 표시할 V 도 넣어 봅시다.

(여기서 Line과 checkbox의 디자인적이 요소가 겹치므로 묶어서 관리해야겠다라고 생각한 당신은 이미 훌륭한 개발자입니다. 나중에 Refactoring할 때 작업해야 겠지요??)

Checkbox Design

 

 

 

Checkbox의 V 눈대중 비율을 표현

* Google에서 Checkbox icon으로 검색한 무료 이미지 입니다.

 

 

Checkbox에 있는 V의 비율을 엄밀하지는 않지만 간단하게 표기해 보았습니다. 이 비율을 가지고 pygame에 그려봅시다.

 

class CheckBox:
    _ACTIVATE_COLOR = (0, 192, 127)
    _DEACTIVATE_COLOR = (192, 192, 192)    
    BACKGROUND_COLOR_MAP = {True: _ACTIVATE_COLOR, False: _DEACTIVATE_COLOR}
    LINE_COLOR = (255, 255, 255)
    LINE_WIDTH = 2

    def __init__(self, x, y, size, margin_ratio = 0.2, is_checked=False):
        self._x = x + size * margin_ratio
        self._y = y + size * margin_ratio
        self._size = size * (1 - margin_ratio * 2)
        self._radius = int(self._size/4)
        self._is_checked = is_checked
        self._checkbox_rect = pg.Rect(self._x, self._y, self._size, self._size)

        self._line1_pos = ((self._x + 0.2 * self._size, self._y + 0.5 * self._size), (self._x + 0.4 * self._size, self._y + 0.7 * self._size))
        self._line2_pos = ((self._x + 0.4 * self._size, self._y + 0.7 * self._size), (self._x + 0.8 * self._size, self._y + 0.3 * self._size))

    def update(self, surface):
        if self._is_checked:
            pg.draw.rect(surface, self.BACKGROUND_COLOR_MAP[self._is_checked], self._checkbox_rect, 0, self._radius)
            pg.draw.line(surface, self.LINE_COLOR, self._line1_pos[0], self._line1_pos[1], self.LINE_WIDTH)
            pg.draw.line(surface, self.LINE_COLOR, self._line2_pos[0], self._line2_pos[1], self.LINE_WIDTH)
        else:
            pg.draw.rect(surface, self.BACKGROUND_COLOR_MAP[self._is_checked], self._checkbox_rect, self.LINE_WIDTH, self._radius)

    def event_handler(self, event: pg.event.Event):
        if event.type == pg.MOUSEBUTTONDOWN:
            if self._checkbox_rect.collidepoint(event.pos):
                self._is_checked = not self._is_checked

 

이렇게 그린다면 다음과 같은 Checkbox를 얻을 수 있습니다.

 

Checkbox의 line이 약간 울퉁불퉁한 것이 아쉽다.

 

이제 이 화면을 실제 Setting화면에 넣을 일만 남았습니다. SettingDisplay 안까먹으셨죠...?

 

 

다음시간에는 저 Setting 화면 사이에 SubSettingDisplay를 집어넣고, 스크롤로 움직일 수 있도록 만들어 보도록 하겠습니다.