python - 如何在已在 tkinter 画布中平滑绘制的线条上重绘线条?
问题描述
我有一些lines
在色彩画布上,也有他们的代码。我想让它们变红但不是同时我想在它们上面画另一条线(红线),但它应该需要不同的时间。例如,对于一条特定的线,这条线应该需要 3 秒才能变红,而另一条线应该需要 7 秒才能变成红色。这就像在前一条上画了另一条红线。
def activator(self, hexagon, duration_time):
if not hexagon.is_end:
self.canvas.itemconfigure(hexagon.drawn, fill="tomato")
self.canvas.itemconfigure(hexagon.hex_aspects.outputs.drawn, fill="tomato")
例如,我希望通过 tinter 的 createpolygon 方法创建的六边形变红,但不会立即变红。它应该与第二个变量duration_time 有关。我的意思是它应该在 duration_time 秒内完成(比如说 3 秒)。有没有办法做到这一点?我的画布上有很多物体,它们应该在特定时间变红。线,圆,多边形..
解决方案
a 上的一条线tk.canvas
由 astart
和一个end
点定义;为了访问线上的点,我们需要首先创建一条仿射线,首先在线上以一定间隔生成许多点,然后将它们与线段连接。
这条仿射线是在单击画布上的项目时创建的,但一开始是隐藏的,然后在很短的时间间隔内逐渐显露出来。
重绘完成后,仿射线将再次隐藏,并且正在重绘的项目设置为其新颜色。
这种“简单”的重绘需要相当多的机器来实现。您可以通过单击一条线来重绘它来尝试它,并查看重绘的动画。
代码:
import random
import tkinter as tk
WIDTH, HEIGHT = 500, 500
class AffinePoint:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return AffinePoint(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return AffinePoint(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return AffinePoint(self.x * scalar, self.y * scalar)
def __iter__(self):
yield self.x
yield self.y
def draw(self, canvas):
offset = AffinePoint(2, 2)
return canvas.create_oval(*(self + offset), *self - offset, fill='', outline='black')
def create_affine_points(canvas, num_points):
"""sanity check"""
for _ in range(num_points):
AffinePoint(random.randrange(0, WIDTH), random.randrange(0, HEIGHT)).draw(canvas)
class AffineLineSegment:
def __init__(self, start, end, num_t=100):
self.start = AffinePoint(*start)
self.end = AffinePoint(*end)
self.num_t = num_t
self.points = []
self._make_points()
self.segments = []
def _make_points(self):
for _t in range(self.num_t):
t = _t / self.num_t
self.points.append(self.start + (self.end - self.start) * t)
def __iter__(self):
for point in self.points:
yield point
def draw(self, canvas):
for p0, p1 in zip(self.points[:-1], self.points[1:]):
self.segments.append(canvas.create_line(*p0, *p1, width=5, state='hidden', fill='red'))
def hide(self, canvas):
for seg in self.segments:
canvas.itemconfigure(seg, state='hidden')
def create_affine_line(canvas, num_lines):
"""sanity check"""
for _ in range(num_lines):
start = random.randrange(0, WIDTH), random.randrange(0, HEIGHT)
end = random.randrange(0, WIDTH), random.randrange(0, HEIGHT)
AffineLineSegment(start, end).draw(canvas)
def select_and_redraw(event):
item = canvas.find_closest(event.x, event.y)[0]
x0, y0, x1, y1 = canvas.coords(item)
canvas.itemconfigure(item, fill='grey25')
canvas.itemconfigure(item, width=1)
a = AffineLineSegment((x0, y0), (x1, y1))
a.draw(canvas)
gen = (segment for segment in a.segments)
redraw(gen, a, item)
def redraw(gen, a, item):
try:
segment = next(gen)
canvas.itemconfigure(segment, state='normal')
root.after(10, redraw, gen, a, item)
except StopIteration:
a.hide(canvas)
canvas.itemconfigure(item, state='normal')
canvas.itemconfigure(item, fill='red')
canvas.itemconfigure(item, width=3)
finally:
root.after_cancel(redraw)
root = tk.Tk()
canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="cyan")
canvas.pack()
canvas.bind('<ButtonPress-1>', select_and_redraw)
# sanity checks
# create_affine_points(canvas, 500)
# create_affine_line(canvas, 100)
for _ in range(10):
start = random.randrange(0, WIDTH), random.randrange(0, HEIGHT)
end = random.randrange(0, WIDTH), random.randrange(0, HEIGHT)
canvas.create_line(*start, * end, activefill='blue', fill='black', width=3)
root.mainloop()
屏幕截图显示正在重绘的过程中的一条线
推荐阅读
- php - PHP联系表单发送但不接收电子邮件
- java - 将日期作为参数传递
- html - primeng,p 表列“重新排序”不起作用
- ios - 带有动画的自定义 UIButton 类
- spring-boot - 使用数据和多部分文件配置 Spring Boot url
- java - Spring-data-jpa:线程安全的唯一插入
- angular - 如何从茉莉花中的角度访问或添加模板引用变量
- c# - 将数据从服务器传递到winform应用程序?
- javascript - Dynamics 365 门户 - 向阵列添加选项
- magento - 将 CC 或 BCC 添加到 Magento 社区联系表