2014-12-30 2 views
1

64x64 타일을 사용하여 '지도 편집기'를 만들고 있습니다. 위치에서 타일을 클릭하고 바꿀 때 캔버스를 업데이트해야합니다. 나는 원래 내가 그것을 업데이트하는 내 이미지를 변경 한 후 내가 Python Kivy Canvas 업데이트가 없습니다.

with self.canvas: 
    Rectangle(source = 'newImage.png') 

를 호출 내 touch_down 클래스에 다음, 하나 개의 클래스에

with self.canvas: 
    Rectangle(source = 'image.png') 

으로 캔버스를 설정합니다.

업데이트 할 수 있지만 매번 새 이미지를 만들어야합니다. 이미 해당 특정 소스 이미지로 해당 사각형을 추가했기 때문에 업데이트가 필요하지 않으며 이미지에 있음을 알 수 없습니다. 변경 되었습니까? 라이언 P

아직 아무것도에 대응

. 이것을 시도했습니다

Class mypaintwidget(Widget): #This is added as a widget to my layout 
    def on_touch_down(self, touch): 
     with self.canvas: 
      self.rect = Rectangle(source = 'image.png') 
     tilepng = pil.open('64x64tile.png') #pil is Python Image Library 
     tilemap = pil.open('image.png')  
     tilemap.paste(tilepng,location) 
     tilemap.save('newimage.png') 
     self.rect.source = 'newimage.png' 

한 번만 업데이트됩니다. 다음 아무것도 (하지만 여전히 늘 그 이미지를 저장하지만, 할 것은 나에게 그것을 보여주지

답변

4

을 당신은 Rectangle 명령을 수정 (또는 제거하고 교체해야하지만 수정이) 쉽게 :.

with self.canvas: 
    self.rect = Rectangle(source='image.png') 

그리고 나중에 :

질문의 두 번째 부분에 관해서는
self.rect.source = 'newImage.png' 

, 문제는 그래서 당신은 newimage.png을 저장하고 다시로드 할 때. 이미지가 Kivy에 로딩에 캐시이다 Kivy는 이미 newimage.png을로드했음을 알고 있습니다. 이것은 Kivy 앱을위한 좋은 디자인이 아닙니다.

on_touch_downRectangle을 작성하면 위젯을 누를 때마다 새 Rectangle이 작성되므로 더 많은 불필요한 그리기 지침을 추가하기 만하면됩니다.

위젯을 여러 개 레이아웃에 추가하면 모두 같은 크기로 전체 창의 크기로 렌더링됩니다. 위젯은 자신의 영역에서 그리기가 제한되지 않으며 앱 내 어디에서나 그릴 수 있습니다. sizepos 매개 변수를 전달하여 Rectangle 명령어가 어디에서 그릴지를 알고 있어야합니다.

마지막으로 이미지를 저장하는 대신 다른 이미지 위에 표시 할 수 있습니다. 이것은 훨씬 더 효율적이며 고유 한 파일 이름을 사용하거나 캐싱 시스템을 망칠 필요가 없습니다.

위젯을 디자인하고 앱을 레이아웃하는 데 훨씬 쉽게 사용할 수 있으므로 Kivy language (kv)을 꼭보아야합니다.

다음은이 작업을 수행 KV를 사용하는 예이다 :

<TileWidget>: 
    tilesource: '' 

    canvas: 
     Color: 
      rgba: 1, 1, 1, 1 
     Rectangle: 
      size: self.size 
      pos: self.pos 
      source: 'image.png' 
     Color: 
      a: 1 if self.tilesource else 0 
     Rectangle: 
      size: self.size 
      pos: self.pos 
      source: self.tilesource 

이 지금은이 모든 무엇을 설명 할 것이다.

<TileWidget>: 

이것은 이름이 <>으로 둘러싸여 있기 때문에 클래스 규칙입니다. TileWidget의 모든 인스턴스에 적용됩니다.

tilesource: '' 

는 여기에서 우리는 setting the value of the property tilesource 있습니다. 그러나 tilesourceWidget 클래스의 자산이 아닙니다! 걱정 마. kv에서 이와 같이 존재하지 않는 속성에 값을 할당하면 해당 속성이 자동으로 만들어집니다. 속성에 할당 할 값은 문자열이므로 Kivy는이 값이 StringProperty이되기를 바랄 것입니다.

이 속성을 만들면 외부에서이 위젯에 영향을 줄 수 있습니다. 나중에이 속성의 값을 사용하여 이미지를 표시합니다.

canvas: 

파이썬의 클래스에서 with self.canvas:을 사용하는 것과 같습니다.

 Color: 
      rgba: 1, 1, 1, 1 

블록 내에서 도면 명령을 추가 할 수 있습니다. 현재 색상이 무엇인지 알 수 없기 때문에 Color instruction으로 시작합니다. 이 색상은 우리가 표시하는 이미지에 색조를 줄 것이므로 아무 색조도 원하지 않으므로 완전한 흰색 색상을 사용합니다.

 Rectangle: 
      size: self.size 
      pos: self.pos 
      source: 'image.png' 

이제 첫 번째 이미지를 렌더링합니다. Rectangle의 크기와 위치가 위젯과 일치하는지 확인합니다. kv에서이 작업을 수행하면 자동으로 바인딩이 생성됩니다. 위젯을 이동하면 크기가 변경되고 Rectangle이 자동으로 업데이트됩니다.

 Color: 
      a: 1 if self.tilesource else 0 

이번에는 색상이 무엇인지 알 수 있습니다. 그러나 우리는 이미지가 설정 될 때까지 다른 것을 그리기를 원하지 않습니다. kv에서 속성은 모든 Python 값을 허용합니다. 이것은 ternary expressions을이 함수 또는 함수 호출이나 산술 등과 같이 사용할 수 있음을 의미합니다. 따라서 self.tilesource이 False (빈 문자열, 위에서 설정 한 기본값)와 같은 경우 색상 (알파 구성 요소) a 속성

 Rectangle: 
      size: self.size 
      pos: self.pos 
      source: self.tilesource 

마지막으로 우리는 선택한 이미지를 렌더링합니다.

class TileWidget(Widget): 
    def on_touch_down(self, touch): 
     if self.collide_point(*touch.pos): 
      self.tilesource = '64x64tile.png' 
      return True 
     return super(TileWidget, self).on_touch_down(touch) 

그것은 접촉을 처리 할 때 collide_point을 사용하는 것이 중요 :

지금, 위젯 자체를 만들기 위해, 우리는 단지 파이썬 약간이 필요합니다. 위젯이 앱의 어느 부분에서나 그릴 수있는 것과 마찬가지로 앱의 어느 위치에서나 터치를 처리 할 수 ​​있습니다. 이렇게하면 행동하기 전에 실제로 터치가 위젯 범위 내에 있는지 확인합니다. 블록 안에 collide_point 블록이 있으면 True를 반환하여 Kivy가이 터치를 처리했다는 사실을 알게하고 처리해야하는 것이 없음을 알립니다. 그렇지 않으면 super()을 호출하여 기본 처리기가 처리하도록합니다.

+0

* self.rectsource = 'newImage.png'* * self.canvas와 다른 클래스에 * 사용하지 않는 것 같습니다 : self.rect = Rectangle (source = 'image.png ') * 오류가 발생합니다. * AttributeError :'class '객체에'rect '속성이 없습니다. * –

+0

이 경우 두 번째 사각형을 다른 캔버스에 추가하려고 할 때 문제가 발생했습니다. 원래 위젯을 참조하여 사각형 위젯을 변경해야합니다. –

+0

나는이 코멘트에 멋지게 보여줄 수있는 코드를 얻지 못한다. 내 질문에 그것을 추가하려고한다. –

관련 문제