Можно ли обеспечить анимацию на изображении? - Ткинтер

Я разрабатываю графический интерфейс в Tkinter и хочу применить анимацию в приведенном ниже GIF к изображению, когда оно появится.

Вот мой код,

from tkinter import *
from PIL import Image, ImageTk

root = Tk()

frame = Frame(root)
frame.pack()

canvas = Canvas(frame, width=300, height=300, bd=0, highlightthickness=0, relief='ridge')
canvas.pack()

background = PhotoImage(file = "background.png")
canvas.create_image(300,300,image=background)

my_pic = PhotoImage(file = "start000-befored.png")
frame.after(1000, lambda: (canvas.create_image(50,50,image=my_pic, anchor=NW))) #and on this image, I want to give the effect.
root.mainloop()

Вместо того, чтобы нажимать кнопку воспроизведения, как показано в GIF, изображение должно автоматически появляться через 1 секунду, как эта анимация, и оставаться на экране. (без возможности закрытия).

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
1 680
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не уверен на 100%, что понял проблему, но я опишу, как анимировать изображение.

Tkinter не содержит функций для анимации изображений, поэтому вам придется писать их самостоятельно. Вам нужно будет извлечь все части изображения, продолжительность части изображения, а затем создать секвенсор для замены частей изображения на вашем дисплее.

Pillow может извлекать последовательности изображений. Изображения WEBP, по-видимому, поддерживают только одну продолжительность кадра, тогда как изображения GIF могут иметь разную продолжительность кадра для каждого фрагмента изображения. Я буду использовать только первую продолжительность для изображений GIF, даже если их много. Насколько я видел, Pillow не поддерживает получение длительности кадра из изображений WEBP, но вы можете прочитать ее из файла, см. Спецификацию контейнера WebP.

Пример реализации:

import tkinter as tk
from PIL import Image, ImageTk, ImageSequence
import itertools

root = tk.Tk()
display = tk.Label(root)
display.pack(padx=10, pady=10)

filename = 'images/animated-nyan-cat.webp'
pil_image = Image.open(filename)
no_of_frames = pil_image.n_frames

# Get frame duration, assuming all frame durations are the same
duration = pil_image.info.get('duration', None)   # None for WEBP
if duration is None:
    with open(filename, 'rb') as binfile:
        data = binfile.read()
    pos = data.find(b'ANMF')    # Extract duration for WEBP sequences
    duration = int.from_bytes(data[pos+12:pos+15], byteorder='big')

# Create an infinite cycle of PIL ImageTk images for display on label
frame_list = []
for frame in ImageSequence.Iterator(pil_image):
    cp = frame.copy()
    frame_list.append(cp)
tkframe_list = [ImageTk.PhotoImage(image=fr) for fr in frame_list]
tkframe_sequence = itertools.cycle(tkframe_list)
tkframe_iterator = iter(tkframe_list)

def show_animation():
    global after_id
    after_id = root.after(duration, show_animation)
    img = next(tkframe_sequence)
    display.config(image=img)

def stop_animation(*event):
    root.after_cancel(after_id)

def run_animation_once():
    global after_id
    after_id = root.after(duration, run_animation_once)
    try:
        img = next(tkframe_iterator)
    except StopIteration:
        stop_animation()
    else:
        display.config(image=img)
    
root.bind('<space>', stop_animation)

# Now you can run show_animation() or run_animation_once() at your pleasure
root.after(1000, run_animation_once)

root.mainloop()

Существуют библиотеки, такие как imgpy, которые поддерживают анимацию GIF, но у меня нет опыта использования таких библиотек.

Добавление

Переменная duration устанавливает скорость анимации. Чтобы замедлить скорость, просто увеличьте продолжительность.

Самый простой способ разместить анимацию на холсте — просто поместить метку на холст, см. пример ниже:

# Replace this code
root = tk.Tk()
display = tk.Label(root)
display.pack(padx=10, pady=10)

# with this code
root = tk.Tk()
canvas = tk.Canvas(root, width=500, height=500)
canvas.pack(padx=10, pady=10)
display = tk.Label(canvas)
window = canvas.create_window(250, 250, anchor='center', window=display)

Тогда вам не придется ничего менять в программе.

Спасибо, это работает! Но изображение, которое отображается, слишком быстрое. Можно ли сделать его немного медленным?

sodmzs1 10.12.2020 11:25

Также можете ли вы сказать мне, как мы можем реализовать это с помощью холста?

sodmzs1 10.12.2020 18:20

Как насчет этого?

figbeam 10.12.2020 20:32

Я изменил значение продолжительности на after_id = root.after(100000, run_animation_once), но скорость такая же. :(

sodmzs1 11.12.2020 01:13

Извините, если я был недостаточно ясен. Перед запуском анимации установите для переменной duration переменную большее значение, например duration = 10000.

figbeam 11.12.2020 07:26

Другие вопросы по теме