Python Forum

Full Version: button image changing but not visually updating
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi complete noob but i've been banging my head against this for 2 days and still can't work out what i'm doing wrong

So i am trying to setup a stack of side button/tabs which change image once clicked, effectively like a radio button just with custom images.

I am seemingly able to get the button's allocated image to change but am not "visual" seeing the change; as in the button image stays the same as first packed. I feel like some sort of update/refresh or "please don't garbage code" or some such is required, root.Update() does nothing and button.update() returns an error.

I feel like i'm making some fundamental error of understanding and just can't narrow down the correct question to ask.
this is a paired down version of what i'm trying to do just using 1 button, but with the back bone to expand to multiple buttons should i work out a fix.

import tkinter
from tkinter import *
from tkinter import ttk

root = Tk()
root.title("tab tester")
root.geometry('800x480')

def Change_Tab(whichTab):
	
	Tab_0_toggle.set(not Tab_0_toggle.get())
	
	print(Tab_0_toggle.get())
	print(Tab_0_icon[Tab_0_toggle.get()])
		
	return 

Tab_0_toggle = IntVar()
Tab_0_toggle.set(False)
Tab_0_icon = [PhotoImage(file='Images\GUI_Tab_Data_Back_sml.png'),PhotoImage(file='Images\GUI_Tab_Data_Active_sml.png')]
Tab_0 = Button(root, image=Tab_0_icon[Tab_0_toggle.get()] , command= lambda: Change_Tab(0)).pack()
any advice would be most welcome
Your code never changes the button image. The Change_Tab function should set a new image for the button. Like this
import tkinter as tk


def toggle(button):
    button.value = not button.value
    button["image"] = button.images[int(button.value)]


root = tk.Tk()
button = tk.Button(root)
button.images = (
    tk.PhotoImage(file="false_img.png"), tk.PhotoImage(file="true_img.png")
)
button.value = True
button["command"] = lambda: toggle(button)
button.pack(padx=50, pady=50)
toggle(button)

root.mainloop()
That code is ugly and would benefit greatly from being written as a class.
import tkinter as tk


class ToggleButton(tk.Button):
    """A button with two states. """
    def __init__(self, parent, on_image, off_image, command=None):
        super().__init__(parent, command=self.toggle, borderwidth=0)
        self.command = command
        self.images = {True: tk.PhotoImage(file=on_image), False: tk.PhotoImage(file=off_image)}
        self["width"] = max(image.width() for image in self.images.values())
        self["height"] = max(image.height() for image in self.images.values())
        self.set(False)

    def get(self):
        """Return button value."""
        return self.value

    def set(self, value):
        """Set button value."""
        self.value = value
        self["image"] = self.images[self.value]
    
    def toggle(self):
        """Toggle button vlaue."""
        self.set(not self.get())
        if self.command:
            self.command(self.value)


root = tk.Tk()
button = ToggleButton(root, on_image="true_img.png", off_image="false_img.png", command=lambda x: print(x))
button.pack(padx=50, pady=50)

root.mainloop()
amazing many thanks will give that a go. Yes had intended on moving it all into a class but wanted to get it to work first as i'm only just learning how to set them up. Thanks so much for making that up for me that will massively help me progress my understanding Big Grin