tkinter - я пытаюсь отключить кнопку вперед / назад, но она не работает - PullRequest
0 голосов
/ 20 марта 2020

Я пытаюсь создать средство просмотра изображений, которое загружает изображения из папки. Он должен иметь кнопки вперед / назад и выйти. Кажется, что он отлично работает с одной проблемой:

Так что я просто беру пути к изображениям с этим:

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

У меня есть пользовательский интерфейс tkinter для средства просмотра изображений:

class UI:
    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.images_paths = get_files_from_folder(images_folder_path, ['.jpg', '.png'])
        self.tk_images = []
        print(get_files_from_folder)
        for image_path in self.images_paths:
            self.tk_images.append(ImageTk.PhotoImage(Image.open(image_path)))

        self.current_image = tk.Label(image = self.tk_images[0])
        self.current_image.grid(column = 0, row = 0, columnspan = 3)

        self.root.mainloop()

И по какой-то причине здесь, когда я использую tk.DISABLED, он просто не отключит его

    def backward(self):

        if self.current_index == 0:
            self.button_backward = self.button_backward = tk.Button(self.root, text = '<<', command = self.backward, state = tk.DISABLED)

        self.current_image.grid_forget()

        self.current_index -= 1
        self.current_image = tk.Label(image = self.tk_images[self.current_index])
        self.current_image.grid(column = 0, row = 0, columnspan = 3)

то же самое для форварда:

    def forward(self):

        self.current_image.grid_forget()

        if self.current_index == len(self.tk_images)-1:
            self.button_forward = self.button_forward = tk.Button(self.root, text = '>>', command = self.forward, state = tk.DISABLED)
        else:
            self.button_forward.state = tk.ACTIVE
        self.current_index += 1
        self.current_image = tk.Label(image = self.tk_images[self.current_index])
        self.current_image.grid(column = 0, row = 0, columnspan = 3)

1 Ответ

0 голосов
/ 20 марта 2020

Что-то не так с вашим текущим кодом, касающимся прямой и обратной 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')

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...