ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Python만으로 어플을 만들어보자 #4 (A SimplePaint App #1)
    Programing/python 어플 개발 2022. 4. 19. 01:35
    반응형

    Python으로 어플만들기 4탄

    : 그림판 어플을 만들어보자

     

    kivy도 설치했고, 간단한 형태의 어플리케이션을 구동하며

    kivy가 어떤 방식으로 진행되는지 대략적으로 파악할 수 있었습니다.

     

    이제는 진짜 튜토리얼로 들어가보겠습니다!

    kivy에서는 kivy를 익히기 위한 튜토리얼로 단순한 형태의 핑퐁게임개발을 제공하고 있습니다.

    그리고 _A first App_에서는 이 핑퐁게임을 메인으로 하고있는 것 같습니다.

        

    하지만 핑퐁게임개발에서는 우리가 겨우 알고 있는 python 뿐만이 아닌,  

    kivy만의 또다른 언어, Kv Design Language를 다루고 있습니다.

    설명만 보면 엄청 간단할 것 처럼 서술되어 있지만 설명에서 생략된 properties들이 많을 것만 같은 느낌적인 느낌입니다...  

    kv design language를 사용하지 않는 다른 튜토리얼부터 진행해보도록 하겠습니다.

      

    Tutorials 에서 핑퐁게임 다음으로 제공하는 튜토리얼은 간단한 그림판 어플리케이션입니다.

    정확히 어떤 형태의 어플리케이션인지는 모르겠지만 일단 튜토리얼을 따라해봅시다.

     

    Python만으로 그림판을 만들어보자

    Basic Consideration

    본격적으로 개발에 들어서기 전, 3가지 중요한 질문을 던져봐야한다고 말합니다.

    • 1) What data does my application process? 어떤 데이터를 처리할 것인가?
    • 2) How do I visually represent that data? 어떻게 데이터를 시각적으로 표현할 것인가?
    • 3) How does the user interact with that data? 어떻게 유저들이 데이터와 interaction 할 것인가?

    우리가 무언가를 개발할 때 대략적으로는 늘 정의된 질문이지만 직접적으로 질문해보는 일은 적은 질문들이네요(물론 회사나 프로젝트팀 등의 조직에서 개발할때라면 표면적인 문서로 정의하는 질문들이지만).

     

    이 튜토리얼에서 우리는 간단한 선 그리기 그림판 프로그램을 만들 것이기 때문에,

    • 3) 유저들이 스크린에 손가락을 터치하는 방식으로 interaction할 것이다.
    • 1) 그동안, 어플은 유저들의 손가락 위치를 기억할 것이고,
    • 2) 해당하는 위치에 선을 표현할 것이다.

    와 같이 정리할 수 있겠습니다.

      

    kivy에서는 버튼, 슬라이드 등의 위젯을 제공하긴 하지만, 경우에 따라서는 위젯을 직접 디자인해야하기도 합니다.  

    최소한(minimal)의 형태로, 반복적/재사용(reusable) 가능한 형태의 위젯을 이번 튜토리얼을 통해 만들어 보겠습니다.

     

    간단한 형태의 그림판 어플리케이션을 개발하기 전,

    먼저 kivy 어플리케이션의 가장 간단한 기본 구조부터 알아야겠죠?

    kivy를 활용한 가장 간단한 형태의 어플리케이션 구동에 대한 내용은 이전의 포스트(https://brain-nim.tistory.com/4)를 참고해주세요.

     

    Python만으로 어플을 만들어보자 #3 (create an application)

    kivy도 설치했으니 이제 kivy공식문서를 따라 어플리케이션 개발을 진행해보고자 합니다. Getting Started 에서 Installing Kivy 를 진행했으니 이제 A first App 이네요. 아직 kivy를 설치하지 않으셨다면 이전

    brain-nim.tistory.com

     

    1. Initial Structure

    from kivy.app import App
    from kivy.uix.widget import Widget
    
    class MyPaintWidget(Widget):
        def on_touch_down(self, touch):
            print(touch)
    
    class MyPaintApp(App):
        def build(self):
            return MyPaintWidget()
    
    if __name__ == '__main__':
        MyPaintApp().run()

    가장 밑바탕이 되는 기본 구조입니다. 지난 포스트에서의 개념과 큰 차이는 없습니다.

    그저 클래스 이름이 몇개 바뀌었을 뿐입니다.

     

    한번 main.py를 실행해, 현재의 어플리케이션이 어떻게 구동하는지 확인해 보겠습니다.

    화면 오른쪽에 떠있는 자그마한 [MyPaint]창이 보이시나요?

    화면을 클릭하면 해당 위치의 비율정보와 픽셀정보가 print됩니다.

    on_touch_down(self,touch)에서 touch는 좌표정보를 보유하고 있습니다.

     

    2. Adding Behaviour (touch -> circle)

    현재는 검은 바탕에, 눌러도 아무런 변화가 없는 이상한 프로그램일 뿐입니다.

    그저 유저의 "MotionEvent"(터치, 클릭 등)가 발생했을 때 내부적으로 데이터를 받아들일 뿐이죠.

     

    이제 조금씩 위젯 기능을 추가해줍시다.

     

    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.graphics import Color, Ellipse
    
    class MyPaintWidget(Widget):
    
        def on_touch_down(self, touch):
            with self.canvas:		 #1
                Color(1, 1, 0)		 #2
                d = 30.			 #3
                Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))  #4
    
    class MyPaintApp(App):
    
        def build(self):
            return MyPaintWidget()
    
    if __name__ == '__main__':
        MyPaintApp().run()

     

    이전과 바뀐건 on_touch_down의 단 4줄입니다.

    (그리고 import Color, Ellipse도 추가되었지만 얘네는 생략하겠습니다.)

    def on_touch_down(self, touch):
        with self.canvas:    #1
            Color(1, 1, 0)   #2
            d = 30.          #3
            Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))  #4
    1. with를 통해 Canvas object를 사용합니다. with 문 안의 내용들은 모두 Canvas를 다루는 내용이 될겁니다.
    2. Color를통해 색깔을 정의해줍니다.
      모두 예상하셨듯 여기서의 색깔 포맷은 RGB이긴한데 kivy의 RGB 값 기준은 0~255가 아니라 0~1인가봅니다.
      우리에게 익숙하게 사용하려면 'value/255'의 형태로 작성해야할 것 같습니다.
      새롭게 색깔을 정의하기 전까지는 계속해서 Color(1,1,0)일겁니다.
    3. d=30 으로 원의 직경(diameter)을 정의해 줬습니다. 바로 아래의 코드에서 사용할 변수입니다.
    4. Ellipse()로 원을 그려줍니다.
      원을 표시할 위치를 pos()로 정의해주는데요, 터치한 해당 위치가 원의 중심이 되도록 -d/2를 추가해줍니다.

    좌: pos(x-d/2,y-d/2) , 우: pos(x,y)

     

    3. Adding Behaviour (touch -> line)

    클릭할 때마다 원이 그려지기는 하지만 아직은 클릭할때 포인트가 생길뿐, 진짜 그림판처럼 드래그할 때 선이 생기지는 않습니다.

    좀 더 기능을 추가해야 할 것 같습니다.

     

    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.graphics import Color, Ellipse, Line
    
    class MyPaintWidget(Widget):
    
        def on_touch_down(self, touch):
            with self.canvas:
                Color(1, 1, 0)
                d = 30.
                Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
                touch.ud['line'] = Line(points=(touch.x, touch.y))  #1
    
        def on_touch_move(self, touch):  #2
            touch.ud['line'].points += [touch.x, touch.y]  #3
    
    
    class MyPaintApp(App):
    
        def build(self):
            return MyPaintWidget()
    
    if __name__ == '__main__':
        MyPaintApp().run()

     

    이번에는 단 3줄이 추가되었습니다.

    touch.ud['line'] = Line(points=(touch.x, touch.y))  #1

    처음 터치/클릭이 일어날 때 해당 위치에 대한 정보를 Line의 points에게 넘깁니다.

    1. Line은 [x1,y1,  x2,y2,  ... , xn,yn]처럼, 각 점의 좌표정보를 리스트,튜플의 형식으로 받습니다.
      그리고 touch.ud를 dictonary<dict>로 설정해서 'line'을 key로, Line 정보를 value로 저장해줍니다.

      저장된 정보가 리스트형태인지 보고싶어서 print문을 넣어봤는데 아쉽게도 Kivy object로 저장되어있네요.

     

     

    def on_touch_move(self, touch):  #2
        touch.ud['line'].points += [touch.x, touch.y]  #3

    2. 위젯에 새로운 메소드 on_touch_move()가 추가되었습니다.
    아직 터치/클릭이 끝나지 않은 상태이기 때문에 위에서 사용한 with self.canvas가 새로 갱신되지 않고 활용되고 있는 상태입니다.

     

    3. 터치/마우스이동으로 새롭게 지정된 위치좌표를 line 딕셔너리에 추가해주면 점이 추가적으로 찍히면서 자동으로 선이 그려집니다.

    그리고 역시 아직 터치/클릭이 끝나지 않은 상태이기 때문에 self.canvas가 새로 갱신되지 않아서 이런 코드의 역할수행이 가능했습니다.

     

    반응형

    댓글

Designed by Tistory.