Tkinter: обновление изображений в ярлыках, которые не доступны напрямую - PullRequest
0 голосов
/ 21 марта 2019

В моем графическом интерфейсе я хотел отобразить изображение, которое меняется в зависимости от некоторого значения.Изображение будет меняться от self.img1 до self.img2.Я создал отдельные классы для контейнера и страниц.Контейнер определяется так:

class Gui(Tk):
    def __init__(self, *args, **kwargs):
        Tk.__init__(self, *args, **kwargs)
        container = Frame(self)
        container.pack(side="top", fill = "both", expand = TRUE)
        container.grid_rowconfigure(0, weight = 1)


        self.MyReading = StringVar()

        self.redpic = Image.open("red.png")
        self.redpic = self.redpic.resize((100,100), Image.ANTIALIAS)
        self.greenpic = Image.open("green.png")
        self.greenpic = self.greenpic.resize((100,100), Image.ANTIALIAS)
        self.img1 = ImageTk.PhotoImage(self.redpic)
        self.img2 = ImageTk.PhotoImage(self.greenpic)

        self.frames={}

        for F in (StartPage, PageOne):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 0, column = 0, sticky = "nsew")

        self.show_frame(StartPage)


    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

И страница, отображающая изображение:

class StartPage(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self,parent)

        label = Label(self, text="StartPage")
        label.grid()
        label1 = Label(self, textvariable = controller.MyReading)
        label1.grid();

        self.label4 = Label(self, image = controller.img1)
        self.label4.grid();
        self.label4.image = controller.img1

        button1 = Button (self, text = "Show PageOne", command = lambda: controller.show_frame(PageOne))
        button1.grid()

В настоящее время отображается img1.Теперь, чтобы создать экземпляр GUI:

root = Gui()
update_reading()
root.mainloop()

update_reading() обновляет мои другие метки, определенные как StringVar().Мне было интересно, как мне обновить label4 (на котором изображено изображение), если я могу только создать / получить доступ к Gui()?Я только знаю, что мог бы изменить с label4 на configure().Есть ли textvariable эквивалент для изображений?

РЕДАКТИРОВАТЬ : Я забыл ввести логику, которую хотел реализовать.Это в основном:

If foo == TRUE:
  --change the image to img1--
else:
  --change the image to img2--

для некоторых foo, существующих за пределами Gui.

EDIT2 : следуя логике предыдущего комментария, я сделал нескольконебольшие изменения в коде В Gui:

class Gui(Tk):
  def __init__(self, *args, **kwargs):
    self.ColorVar = DoubleVar()

И в пределах StartPage() изменения:

class StartPage(Frame):
  def __init__(self, parent, controller):
    controller.ColorVar.trace("w",self.IdkChief(controller))

  def IdkChief(self, controller):
        global val1
        if float(val1) < 2.50 :
            self.label4.configure(image = controller.img2)
            self.label4.image = controller.img2
        else:
            self.label4.configure(image = controller.img1)
            self.label4.image = controller.img1

Тогда изменения в ColorVar определяются в update_reading() как таковой:

def update_reading():
    global val1
    root.ColorVar.set(val1)
    root.after(100,update_reading)

Где val1 - это изменяемое значение с плавающей запятой.Я решил изменить его с булевой логики на плавающую, чтобы повысить гибкость.После этого мне выдалась бы общая ошибка

Исключение в обратном вызове Tkinter (последний последний вызов):
Файл "C: \ Users \ AppData \ Local \ Programs \ Python \ Python37 \ lib\ tkinter__init __. py ", строка 1705, в call return self.func (* args) TypeError: объект 'NoneType' не вызывается

Эта ошибка повторяется до тех пор, пока не появится GUIзакрыто.

1 Ответ

0 голосов
/ 21 марта 2019

Вы можете использовать функцию переменной tkinter trace, чтобы настроить функцию обратного вызова, которая будет выполняться при каждом обновлении переменной.Внутри функции обратного вызова вы можете обновить метку, основываясь на значении переменной.

Ниже приведены примеры блоков кода (в зависимости от вашего дизайна размещенного кода) для достижения вашей цели:

class Gui:
    def __init__(self, *args, **kwargs):
        ...
        self.ColorVar = DoubleVar()
        ...

class StartPage(Frame):
    def __init__(self, parent, controller):
        ...
        # register a callback to be executed whenever variable is modified
        controller.ColorVar.trace('w', lambda *args: self.IdkChief(controller))

    def IdkChief(self, controller):
        img = controller.img1 if controller.ColorVar.get() < 2.5 else controller.img2
        self.label4.config(image=img)
...