껐다가 새로 시작할 때는 먼저 터미널을 통해 venv를 activate 시키기

source venv/Scripts/activate

 

1. 시계를 만들기 위해 clock 폴더 생성

# clock 폴더를 만들 경로에서 clock 폴더 생성 명령어 입력
$ mkdir clock

# clock 폴더로 경로를 이동하여 pynecone 프로젝트 생성
$ cd clock
$ pc init

 

2. 시계 코드 작성

from pcconfig import config
import pynecone as pc
from datetime import datetime
import pytz
import asyncio

class State(pc.State):

    # 초기 시간을 표시할 zone
    zone: str = "Asia/Seoul"
    # 초기에 시계를 작동시킬지 여부를 False로
    start: bool = False

    # pytz 라이브러리를 통해 각 zone의 현재 시간을 얻어옴
    # AM, PM으로 오전, 오후를 구분하기 위해 12로 나눈 나머지 값을 hour에 저장
    @pc.var
    def hour(self):
        return datetime.now(pytz.timezone(self.zone)).hour % 12
    
    @pc.var
    def minute(self):
        return datetime.now(pytz.timezone(self.zone)).minute
    
    # 분과 초의 표시 형식은 "00"처럼 두 자리 형태
    @pc.var
    def minute_display(self):
        return f"{self.minute:02}"
    
    @pc.var
    def second(self):
        return datetime.now(pytz.timezone(self.zone)).second
    
    @pc.var
    def second_display(self):
        return f"{self.second:02}"
    
    # hour가 12보다 작으면 오전이므로 "AM", 12시부터는 오후이므로 "PM"
    @pc.var
    def meridiem(self):
        if datetime.now(pytz.timezone(self.zone)).hour < 12:
            return "AM"
        else:
            return "PM"
    
    # 시계의 분침과 초침은 1분, 1초에 6도씩 움직이므로 각 분과 초에 6을 곱하여 정상에서 몇 도 떨어져있는지 계산
    # 시계의 시침은 시계 한바퀴를 12에 나누어 돌아서 한 시간 당 30도씩 움직임
    @pc.var
    def minute_rotation(self):
        minute = self.minute * 6 - 90
        return f"rotate({minute}deg)"
    
    @pc.var
    def hour_rotation(self):
        hour = self.hour * 30 - 90
        return f"rotate({hour}deg)"
    
    @pc.var
    def second_rotation(self):
        second = self.second * 6 - 90
        return f"rotate({second}deg)"
    
    # asyncio.sleep함수를 사용하여 1초의 지연을 발생시킨 후 tick을 보냄
    # 시계 동작 버튼이 True일때만 tick을 보냄
    async def tick(self):
        if self.start:
            await asyncio.sleep(1)
            return self.tick
    
    # 시계 동작 여부를 False, True로 바꾸는 스위치
    # True일 때만 tick 함수를 실행
    def flip_switch(self, start):
        self.start = start
        if self.start:
            return self.tick

# 시침, 분침, 초침 설정
def current_hour(hour):
    return pc.divider(
        transform = hour,
        width = "16em",
        position = "absolute",
        border_style = "solid",
        border_width = "4px",
        border_image = "linear-gradient(to right, rgb(250, 250, 250) 50%, black 100%) 0 0 100% 0",
        z_index = 0,
    )

def current_minute(minute):
    return pc.divider(
        transform = minute,
        width = "18em",
        position = "absolute",
        border_style = "solid",
        border_width = "4px",
        border_image = "linear-gradient(to right, rgb(250, 250, 250) 50%, red 100%) 0 0 100% 0",
        z_index = 0,
    )

def current_second(second):
    return pc.divider(
        transform = second,
        width = "20em",
        position = "absolute",
        border_style = "solid",
        border_width = "4px",
        border_image = "linear-gradient(to right, rgb(250, 250, 250) 50%, blue 100%) 0 0 100% 0",
        z_index = 0,
    )

# 메인 페이지
def clock():
    # 화면 가운데
    return pc.center(
        # 수직으로
        pc.vstack(
            # 맨 위에 동그라미(시계) 생성
            pc.circle(
                # 동그라미 안에 작은 동그라미 생성
                pc.circle(
                    width = "1em",
                    height = "1em",
                    border_width = "thick",
                    border_color = "#43464B",
                    z_index = 1,
                ),
                # 시계 안에 시침, 분침, 초침 추가
                current_minute(State.minute_rotation),
                current_hour(State.hour_rotation),
                current_second(State.second_rotation),
                # 그 외 동그라미 스타일 설정
                border_width = "thick",
                border_color = "#43464B",
                width = "25em",
                height = "25em",
                bg = "rgb(250, 250, 250)",
                box_shadow = "dark-lg",
            ),

            # 동그라미(시계) 다 만들고 그 아래에 시간 텍스트로 표시
            # 텍스트는 수평으로 추가
            pc.hstack(
                pc.hstack(
                    # 부모 State 클래스에 접근할 수 있는 pc.heading
                    pc.heading(State.hour),
                    pc.heading(":"),
                    pc.heading(State.minute_display),
                    pc.heading(":"),
                    pc.heading(State.second_display),
                    pc.heading(State.meridiem),
                    border_width = "medium",
                    border_color = "#43464B",
                    border_radius = "2em",
                    padding_x = "2em",
                    bg = "white",
                    color = "#333",
                ),
                # 시계 작동 여부 스위치도 시간 텍스트 옆에 추가
                pc.switch(is_checked = State.start, on_change = State.flip_switch),
            ),

            # 동그라미 밑에 시간 텍스트 밑에 select 박스 추가
            pc.select(
                # select 목록
                [
                    "Asia/Seoul",
                    "Australia/Sydney",
                    "Europe/Paris",
                    "Europe/Moscow",
                    "US/Pacific",
                    "US/Eastern",
                ],
                # 초기에 select 박스에 표시되는 텍스트
                placeholder = "Select a time zone",
                # select 값이 바뀌는 Event가 발생하면 작동하는 Event Handler
                on_change = State.set_zone,
                bg = "#white",
            ),
            padding = "5em",
            border_width = "medium",
            border_color = "#43464B",
            border_radius = "25px",
            bg = "#ededed",
            text_align = "center",
        ),
        padding = "5em",
    )


app = pc.App(state=State)
app.add_page(clock, title = "Clock")
app.compile()

 

3. 알게 된 점

 1) State의 요소

  • Basic Vars: 흔히 알고 있는 변수 / Event Handler에 의해서 변할 수 있는 값
  • Computed Vars: 다른 변수들의 함수 / 직접 생성될 수 없고 다른 변수에 의해 파생됨
  • Events: 앱 내에서 발생하여 Event Handler를 작동시키는 행동
  • Event Hanlders: Event에 의해 반응하는 함수 / State 클래스에서 함수로 정의됨

 

'Python > pynecone' 카테고리의 다른 글

[pynecone] 02. pynecone으로 counter app 만들기  (0) 2023.01.18
[pynecone] 01. 설치  (0) 2023.01.18

+ Recent posts