Как перерисовать линию на линии, которая уже гладко нарисована в tkinter canvas? - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть немного lines на холсте tinter, а также есть их код.Я хочу сделать их красными, но не в то же время, я хочу нарисовать еще одну линию (красную линию), но они должны занять другое время.например, для одной конкретной строки требуется 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 секунды).есть ли способ сделать это?У меня на холсте много объектов, которые должны покраснеть в течение определенного времени.линия, круг, многоугольник ..

Ответы [ 2 ]

1 голос
/ 21 апреля 2019

Линия на tk.canvas определяется точками start и 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()

Снимок экрана, показывающийлиния в процессе перерисовки

enter image description here

0 голосов
/ 12 апреля 2019

Попробуйте что-то вроде этого

from tkinter import *
import numpy as np

root = Tk()


def lighter(color, percent):
    color = np.array(color)
    white = np.array([255, 255, 255])
    vector = white-color
    return tuple(color + vector * percent)


def Fade(line, start_rgb, percentage, times, delay):
    '''assumes color is rgb between (0, 0, 0) and (255, 255, 255) adn percentage a value between 0.0 and 1.0'''
    new_color = lighter(start_rgb, percentage)
    red, blue, green = new_color
    red = int(red)
    blue = int(blue)
    green = int(green)
    new_hex = '#%02x%02x%02x' % (red, blue, green)

    canvas.itemconfigure(line, fill=new_hex)
    if times > 0:
        root.after(delay, lambda: Fade(line, new_color, percentage, times - 1, delay))


canvas = Canvas(root, bg="black")
canvas.pack()

line = canvas.create_line(0, 0, 100, 100, width=10)
Fade(line, (0, 0, 50), 0.01, 1000, 10)
root.mainloop()
...