Python Forum

Full Version: Can't get tkinter button to change color based on changes in data
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I'm trying to get a "Save" button color to change color if any form data has been changed. I got this to work once before but misplaced my flash drive with it on there. Current attempts are failing. Any pointers? There's an unseen module which talks to the database which I don't think will make a difference here. The code I'm referring to is down towards the bottom. Thanks in advance:

from tkinter import *
from tkinter import ttk
import tkinter as tk
import dbConnect as db

db.ssConnect()


rowspacer=40
colspacer=40

class demoForm():

    def fillDemoForm():
        root = Tk()
        fName = tk.StringVar().trace_add('write',demoForm.changeButton)
        lName = tk.StringVar().trace_add('write',demoForm.changeButton)    
        fName = db.getFlds.getFld(index=0,fldName='Fname',tblName='Name2')
        lName = db.getFlds.getFld(index=0,fldName='Lname',tblName='Name2')

        

        btnSave = ttk.Button(text="Save")
        btnSave.place(x=colspacer*6, y=rowspacer*1)

        lblFname= tk.Label(text='fName').place(x=10, y=10)
        fldFname = Entry(root,textvariable=fName )
        fldFname.place(x=60, y= 10)
        fldFname.delete(0,END)
        fldFname.insert(0,fName)

        lblLname= tk.Label(text='lName').place(x=10, y=rowspacer)
        fldLname= tk.Entry(root, textvariable=lName)
        fldLname.place(x=60, y= rowspacer)
        fldLname.delete(0,END)
        fldLname.insert(0,lName)

        root.geometry('325x250')
        root.configure(background = "lightgray")

        root.mainloop()

    def changeButton():
        btnSave=Button(root, text="Save",bg="red")

demoForm.fillDemoForm()
Here's an example class that uses trace_add:
from tkinter import *
from tkinter import ttk


class TryTraceBack:
    def __init__(self, parent):
        self.parent = parent
        self.parent.geometry("200x130")
        self.parent.grid_rowconfigure(0, weight=1)
        self.parent.grid_columnconfigure(0, weight=1)

        self.var = StringVar()


    def validate(self, var, index, mode):
        print(f"Traced variable {self.var.get()}")

    def CreateWidgets(self):
        # registering the observer
        self.var.trace_add('write', self.validate)

        frame = Frame(self.parent)
        frame.grid(row=0, column=0, sticky="NESW")
        frame.grid_rowconfigure(0, weight=1)
        frame.grid_columnconfigure(0, weight=1)

        label = Label(frame, textvariable = self.var).grid(row=0, column=0, sticky='EW')

        entry = Entry(frame, textvariable = self.var).grid(row=1, column=0, sticky='EW')


def main():
    root = Tk()

    ttb = TryTraceBack(root)
    ttb.CreateWidgets()

    root.mainloop()


if __name__ == '__main__':
    main()
Here is one way to go about it.
import tkinter as tk
 
rowspacer=40
colspacer=40
 
class demoForm():
	def __init__ (self) :
		self.root = tk.Tk ()
		self.fName = tk.StringVar ()
		self.fName.trace_add ('write', self.changeButton)

	def fillDemoForm(self):
		self.btnSave = tk.Button(text="Save")
		self.btnSave.place(x=colspacer*6, y=rowspacer*1)
 
		blFname= tk.Label(text='fName').place(x=10, y=10)
		fldFname = tk.Entry(self.root,textvariable=self.fName )
		fldFname.place(x=60, y= 10)
		fldFname.delete(0,tk.END)
		fldFname.insert(0,self.fName)
 
		self.root.geometry('325x250')
		self.root.configure(background = "lightgray")
 
		self.btnSave.config (bg = 'lightgray') 
		self.root.mainloop()

	def changeButton(self, *args):
		self.btnSave.config (bg="red")
 
test = demoForm ()
test.fillDemoForm()
import tkinter as tk

root = tk.Tk()
root['padx'] = 8
root['pady'] = 5

my_var = tk.StringVar()
my_var2 = tk.StringVar()

label = tk.Label(root, text='fName')
label.grid(column=0, row=0, sticky='new', pady=2)

entry = tk.Entry(root, textvariable=my_var)
entry.grid(column=1, row=0, sticky='new', pady=2)
entry.insert(0, 'john')

label2 = tk.Label(root, text='lName')
label2.grid(column=0, row=1, sticky='new', pady=2)

entry2 = tk.Entry(root, textvariable=my_var2)
entry2.grid(column=1, row=1, sticky='new', pady=2)
entry2.insert(0, 'doe')

btn = tk.Button(root, text='Save')
btn.grid(column=0, row=2, columnspan=2, sticky='ew', pady=2)

def callback(var, index, mode):
    btn.configure(bg='red')

my_var.trace_add('write', callback)
my_var2.trace_add('write', callback)

root.mainloop()
(Feb-13-2022, 04:08 AM)BashBedlam Wrote: [ -> ]
test = demoForm ()
test.fillDemoForm()

This worked. Thank you very much.
Thank you everyone for your input. Much appreciated.