Tkinker Как перебрать изображения? - PullRequest
1 голос
/ 19 апреля 2019

У меня есть много изображений base64, сохраненных в кадре данных pandas df_time_text_frames.Теперь я хотел бы сделать простую программу, которая показывает мне изображения и имеет кнопку СЛЕДУЮЩАЯ или ПРЕДЫДУЩАЯ, чтобы перемещаться по изображениям.

Я пытался:

Я определяю функциюload_next_img, который срабатывает, когда я нажимаю tk.Button, называемый next, и который затем должен отображать кадр, заданный глобальным counter, который увеличивается каждый раз, когда я нажимаю эту кнопку.

Еще не реализовано:

У меня была бы аналогичная функция для кнопки previous, которая вычла бы 1 из глобальной переменной counter

import tkinter as tk
from PIL import ImageTk, Image


global counter
counter = 0
def load_next_img(counter):
    global tk_image
    image_data_base64_encoded_string = df_time_text_frames["Frame_(base_64)"][counter]
    image = tk.PhotoImage(image_data_base64_encoded_string)
    tk.Label(root, image=im).pack()
    counter += 1

root =  tk.Tk() 

nextbutton = tk.Button(text="next", command=load_next_img(counter))
nextbutton.pack()

root.mainloop()

First ofвсе, это не работает.Я получаю:

---------------------------------------------------------------------------
TclError                                  Traceback (most recent call last)
<ipython-input-24-bc9ac8d3c57e> in <module>()
     14 root =  tk.Tk()
     15 root = tk.Toplevel()
---> 16 nextbutton = tk.Button(text="next", command=load_next_img(counter))
     17 nextbutton.pack()
     18 

<ipython-input-24-bc9ac8d3c57e> in load_next_img(counter)
      9     image_data_base64_encoded_string = df_time_text_frames["Frame_(base_64)"][counter]
     10     image = tk.PhotoImage(image_data_base64_encoded_string)
---> 11     tk.Label(root, image=im).pack()
     12     counter += 1
     13 

~\Anaconda3\lib\tkinter\__init__.py in __init__(self, master, cnf, **kw)
   2761 
   2762         """
-> 2763         Widget.__init__(self, master, 'label', cnf, kw)
   2764 
   2765 class Listbox(Widget, XView, YView):

~\Anaconda3\lib\tkinter\__init__.py in __init__(self, master, widgetName, cnf, kw, extra)
   2294             del cnf[k]
   2295         self.tk.call(
-> 2296             (widgetName, self._w) + extra + self._options(cnf))
   2297         for k, v in classes:
   2298             k.configure(self, v)

TclError: image "pyimage8" doesn't exist

... и мне интересно, есть ли гораздо более простой / лучший способ сделать это?

РЕДАКТИРОВАТЬ 1: Я пыталсяследующее:

import tkinter as tk
from PIL import ImageTk, Image


global counter
counter = 0


def load_next_img(counter):
    #global counter
    # rest of your code
    counter += 1
    global tk_image
    image_data_base64_encoded_string = df_time_text_frames["Frame_(base_64)"][counter]
    image = tk.PhotoImage(image_data_base64_encoded_string)
    tk.Label(root, image=im).pack()
    counter += 1

root =  tk.Tk() 

nextbutton = tk.Button(text="next", 
                        command=lambda counter: load_next_image(counter))
nextbutton.pack()

root.mainloop()

Я не получаю ошибки, но изображение не отображается.

Ответы [ 2 ]

2 голосов
/ 19 апреля 2019

Я вижу несколько проблем с этим, которые могут или не могут быть причиной проблемы.

  1. Нет необходимости использовать счетчик в качестве аргумента для load_next_image, поскольку вы уже объявили его глобально. Удалите счетчик в качестве аргумента и включите счетчик в пространство имен функций следующим образом:
global counter
counter = 0
def load_next_image():
    global counter
    # rest of your code
    counter += 1
  1. Письмо command=load_next_image(counter) не делает то, что вы думаете, оно делает. Команда принимает либо «Нет», либо вызываемый объект, например функцию. Что вы делаете, так это устанавливаете команду равной выводу load_next_image(counter) при создании кнопки, которая равна None, поскольку load_next_image ничего не возвращает.

    Если вам не нужно передавать какие-либо параметры функции, правильный путь - command=load_next_image, который устанавливает команду равной фактическому дескриптору функции. Когда кнопка нажата, ваша функция будет выполнена.

    Если вам нужно передать аргумент функции (иногда это необходимо), вы должны использовать оператор lambda (см. this ).

 nextbutton = tk.Button(text="next", 
                        command=lambda counter: load_next_image(counter))

Опять же, это работает, потому что лямбда возвращает дескриптор анонимной функции, а не результат самой функции. Однако в вашем случае вам не нужно беспокоиться об этом, если вы реализуете счетчик как глобальную переменную, как я упоминал в (1) (поскольку вам не нужно передавать аргумент).

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

Если возможно, не могли бы вы поделиться ссылкой на ваш полный исходный код, поскольку это было бы легче отладить со всем кодом.

Из первоначального прочтения я вижу эту строку.

tk.Label(root, image=im).pack()

Но im не определено в этой области.Попробуйте изменить im на image и проверьте, не появляется ли снова ошибка

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

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