2011-08-27 3 views
4

하나의 캔버스에 그려진 개체를 복제하지 않고 다른 캔버스의 내용을 표시하는 방법을 찾고 있습니다. 두 번째 캔버스는 첫 번째 캔버스에서 그려지는 것을 입력으로 사용하는 디스플레이 일 필요가 있습니다.Tkinter - 다른 캔버스에 내용을 표시하는 두 번째 캔버스 만들기

.postscript 메서드는 파일이나 변수에 내용을 쓰지만, 다른 캔버스를 이미지로 표시하는 방법 (가능한 경우)을 모르겠습니다.

편집 : 제 운영 체제가 Windows라는 것을 잊었습니다. 누군가가 나에게 크로스 플랫폼 솔루션을 알려줄 수 있다면 좋을 것입니다.

Edit2 : 내가 개체를 복제하여 수행하고 싶지 않은 이유는 이동하고 일부 간격으로 일부가 파괴되어 새로운 개체가 만들어지기 때문입니다. 또한 실시간 시스템이기 때문에 객체를 복제하면 동작이 느려질 수 있습니다.

+0

사용중인 운영 체제는 무엇입니까? –

+0

왜 솔루션에서 캔버스의 객체를 복제 할 수있게 허용해야합니까? –

+0

@MakerDrone : 몇 개의 개체가 있습니까? Tkinter는 수천 개의 물체, 심지어 움직이는 물체도 쉽게 처리 할 수있었습니다. 분명히 하나가 아닌 두 개의 객체를 그리는 데 두 배의 시간이 걸리지 만, 몇 천 개의 객체 만 있으면 성능이 눈에 띄지 않을 수 있습니다. –

답변

3

기본 제공 방법이 없습니다. 캔버스는 어떤 종류의 피어링이나 복제도 지원하지 않습니다. 그러나 임베디드 위젯이 없으면 두 번째 캔버스에 모든 객체의 복사본을 유지하는 것이 매우 쉽고 빠릅니다.

간단한 방법은 캔버스 위젯을 서브 클래스화한 다음 피어 캔버스에 그리기 위해 draw_line, draw_oval, coords 등의 새로운 구현을 만드는 것입니다. 다음 예제는 이와 같이 세 가지 캔버스를 서로 다른 속도로 아래로 이동하는 1000 개의 객체로 조정하는 방법을 보여줍니다.

import Tkinter as tk 
import random 

class SampleApp(tk.Tk): 
    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 
     self.canvas1 = PeeredCanvas(self, width=300, height=300, border=1, relief="sunken") 
     self.canvas2 = PeeredCanvas(self, width=300, height=300, border=1, relief="sunken") 
     self.canvas3 = PeeredCanvas(self, width=300, height=300, border=1, relief="sunken") 
     self.canvas1.add_peer(self.canvas2) 
     self.canvas1.add_peer(self.canvas3) 
     toolbar = tk.Frame(self) 
     clear_button = tk.Button(self, text="Refresh", command=self.refresh) 
     clear_button.pack(in_=toolbar, side="left") 
     toolbar.pack(side="top", fill="x") 
     self.canvas1.pack(side="left", fill="both", expand=True) 
     self.canvas2.pack(side="left", fill="both", expand=True) 
     self.canvas3.pack(side="left", fill="both", expand=True) 
     self.animate(10) 

    def animate(self, delay): 
     '''Move all items down at a random rate''' 
     for item in self.canvas1.find_all(): 
      delta_x = 0 
      delta_y = random.randrange(1, 4) 
      self.canvas1.move(item, delta_x, delta_y) 
     self.after(delay, self.animate, delay) 

    def refresh(self, count=100): 
     '''Redraw 'count' random circles''' 
     self.canvas1.delete("all") 
     width=self.canvas1.winfo_width() 
     height=self.canvas1.winfo_height() 
     for i in range(count): 
      if i%2 == 0: 
       tags = ("even",) 
      else: 
       tags = ("odd",) 
      x = random.randrange(10, width-10) 
      y = random.randrange(10, height-10) 
      radius = random.randrange(10,100, 10)/2 
      self.canvas1.create_oval([x,y, x+radius, y+radius], tags=tags) 
     self.canvas1.itemconfigure("even", fill="red", outline="white") 
     self.canvas1.itemconfigure("odd", fill="white", outline="red") 

class PeeredCanvas(tk.Canvas): 
    '''A class that duplicates all objects on one or more peer canvases''' 
    def __init__(self, *args, **kwargs): 
     self.peers = [] 
     tk.Canvas.__init__(self, *args, **kwargs) 

    def add_peer(self, peer): 
     if self.peers is None: 
      self.peers = [] 
     self.peers.append(peer) 

    def move(self, *args, **kwargs): 
     tk.Canvas.move(self, *args, **kwargs) 
     for peer in self.peers: 
      peer.move(*args, **kwargs) 

    def itemconfigure(self, *args, **kwargs): 
     tk.Canvas.itemconfigure(self, *args, **kwargs) 
     for peer in self.peers: 
      peer.itemconfigure(*args, **kwargs) 

    def delete(self, *args, **kwargs): 
     tk.Canvas.delete(self, *args) 
     for peer in self.peers: 
      peer.delete(*args) 

    def create_oval(self, *args, **kwargs): 
     tk.Canvas.create_oval(self, *args, **kwargs) 
     for peer in self.peers: 
      peer.create_oval(*args, **kwargs) 


app = SampleApp() 
app.mainloop() 
+0

고마워요, Bryan, 좋은 생각입니다. 하지만 난 더 간단한 솔루션을 찾은 것 같아요 : – MakerDrone

+0

난 그냥 첫 번째 캔버스의 모든 개체 구성 옵션 값을 누른 다음 두 번째 캔버스에 기능을 업데이 트 난 모든 개체 (만약 있다면)를 삭제하고 다시 첫 번째 캔버스의 각 옵션을 사용합니다. 반복적 인 after() 호출을 통해이 업데이트를 수행 할 수 있으므로 동일한 새로 고침 빈도를 사용할 필요가 없습니다. – MakerDrone

관련 문제