Что-то не так с вашим текущим кодом, касающимся прямой и обратной Button
s команд. Что касается отключения Button
s, это можно сделать, вызвав их метод config()
- , а не , создав новое или присвоив новое значение атрибуту state
существующих (т. Е. * 1007). *).
Точно так же не рекомендуется постоянно создавать новые tk.Label
виджеты при каждом нажатии одной из кнопок и изменении изображения на ней. Лучше изменить параметр image=
существующего Label
. Это также часто упрощает то, что необходимо сделать.
Кроме того, ваша логика c для фиксации self.current_index
была некорректной и позволяла ей выходить за пределы диапазона и IndexError
s. Это сложнее, чем я ожидал, но я думаю, что нашел хороший способ справиться с этим, а именно, поместив все logi c в закрытый метод _change_current_index()
и вызвав его из функций прямого и обратного вызова.
Наконец, пользователь @ acw1668 отметил, что загрузка всех изображений в память при запуске программы может быть медленной. Чтобы избежать этого, я заменил список всех загруженных вами изображений (self.tk_images
) вызовами другого нового частного метода с именем _open_image()
, который кэширует свои результаты, применяя к нему декоратор functools.lru_cache
. Это заставляет метод запоминать, какие значения он уже возвратил для ограниченного числа индексов, тем самым ограничивая количество их в памяти одновременно.
Примечание. Я также переформатировал код, чтобы лучше соответствовать PEP 8 - Руководство по стилю для Python Code руководств, чтобы сделать его более читабельным.
from functools import lru_cache
import tkinter as tk
import os
from PIL import Image, ImageTk
class UI:
IMG_CACHE_SIZE = 10
def __init__(self, icon_path, images_folder_path):
self.current_index = 0
self.root = tk.Tk()
self.root.title('Images')
# self.root.iconbitmap(icon_path)
self.button_quit = tk.Button(self.root, text='Quit', padx=60, command=self.root.quit)
self.button_forward = tk.Button(self.root, text='>>', command=self.forward)
self.button_backward = tk.Button(self.root, text='<<', command=self.backward)
self.button_quit.grid(row=1, column=1)
self.button_forward.grid(row=1, column=2)
self.button_backward.grid(row=1, column=0)
self.image_paths = get_files_from_folder(images_folder_path, ['.jpg', '.png'])
self.current_image = tk.Label(image=self._open_image(0))
self.current_image.grid(column=0, row=0, columnspan=3)
self._change_current_index() # Initializes fwd and bkd button states.
self.root.mainloop()
@lru_cache(maxsize=IMG_CACHE_SIZE)
def _open_image(self, i):
image_path = self.image_paths[i]
return ImageTk.PhotoImage(Image.open(image_path))
def backward(self):
self._change_current_index(-1)
def forward(self):
self._change_current_index(1)
def _change_current_index(self, delta=0):
self.current_index += delta
# Update state of forward and backward buttons based on new index value.
bkd_state = (tk.DISABLED if self.current_index == 0 else tk.ACTIVE)
self.button_backward.config(state=bkd_state)
fwd_state = (tk.DISABLED if self.current_index == len(self.image_paths)-1 else tk.ACTIVE)
self.button_forward.config(state=fwd_state)
# Update image on Label.
self.current_image.config(image=self._open_image(self.current_index))
def get_files_from_folder(path, allowed_extensions):
found_paths = []
for (dir_path, _, file_names) in os.walk(path):
for file_name in file_names:
for allowed_extension in allowed_extensions:
if file_name.lower().endswith(allowed_extension.lower()):
found_paths.append(os.path.join(dir_path, file_name))
break
return found_paths
if __name__ == '__main__':
UI('.', './images_test')