Tkinter - 让第二个画布显示第一个画布的内容
我想找个方法,让一个画布显示另一个画布的内容,但不想复制里面的图形。第二个画布只是用来显示第一个画布上画的东西。
我知道 .postscript 方法可以把内容写到文件或变量里,但我不太清楚(如果可以的话)怎么让另一个画布把这些内容当成图片来显示。
补充一下,我的操作系统是Windows。如果有人能告诉我一个跨平台的解决方案,那就太好了。
再补充一点,我不想通过复制对象来实现,因为这些对象是会移动的,并且在某个时间间隔内,有些对象会被销毁,同时又会创建新的对象。而且这是一个实时系统,复制对象及其行为可能会导致系统变慢。
1 个回答
5
这个功能没有现成的方法可以实现。画布(canvas)不支持任何形式的共享或复制。不过,如果你没有嵌入的控件,保持所有对象的副本在第二个画布上其实很简单且快速。
一种简单的方法是对画布控件进行子类化,也就是创建一个新的画布类,然后重新实现一些方法,比如画线(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()