Reputation: 131
Let me elaborate the process. Following is the sample code snippet of my application
import tkinter as tk
class ldo(Frame):
def __init__(self, master = None):
Frame.__init__(self,master)
self.grid()
self.appOutline()
def appOutline(self):
self.masterframe1 = Frame(self.master,width=300,height=300)
self.masterframe1.grid(sticky=N,padx=20)
self.masterframe2 = Frame(self.master,width=300,height=100)
self.masterframe2.grid(sticky=S,padx=20)
self.addtabbutton = Button(self.masterframe2,text="Add Step", width=10, command=self.popup2, bg="sienna1")
self.addtabbutton.grid(row=0,column=0,sticky=EW)
self.runallbutton = Button(self.masterframe2,text="Run All", width=10, command=self.underprocess, bg="sienna1",state=DISABLED)
self.runallbutton.grid(row=0,column=1,sticky=EW)
self.runselbutton = Button(self.masterframe2,text="Run Selected", width=10, command=self.popup2, bg="sienna1",state=DISABLED)
self.runselbutton.grid(row=0,column=2,sticky=EW)
def popup2(self):
self.child = Toplevel()
self.child.geometry("300x300")
self.child.title("Secondary")
self.label1 = Label(self.child,text="Your input")
self.label1.pack()
self.entryinp = StringVar()
self.entry1 = Entry(self.child,textvariable=entryinp)
self.entry1.pack()
self.submit = Button(self.child,text="Submit",command=self.evaluation,bg="pink")
self.submit.pack()
def evaluation(self):
self.inputValue = self.entry1.get()
self.steps = Button(self.masterframe1,text=self.inputValue,command=self.colorchange,bg="light blue")
self.steps.pack()
self.runallbutton.config(state=NORMAL)
self.child.destroy()
def colorchange(self):
self.steps.config(bg="white")
self.runselbutton.config(state=NORMAL)
def underprocess(self):
print("processing...")
if __name__ == "__main__":
app = ldo()
app.master.title("Primary")
app.mainloop()
Below screenshot is the output of my app. My need is I want to change the colour of button I click in Primary interface, but what happens is whatever the button I click, it is changing colour of the last button. I tried using lambda, but I doubt if I am using it correctly. The above snippet is working except the colour change part. Please guide me on how to get this done.
Also, I want "Run Selected" button to print (text of) that particular button I clicked.
P.S.: I have checked in this link too yet not solvable.
Upvotes: 1
Views: 744
Reputation: 4513
One option is to use lambda
or functools.partial
and pass the instance of the boton as argument. Instead of setting the callback when the button is instantiated (the reference does not yet exist) you can use the config
method. On the other hand you can use an instance attribute to store the references of the selectable buttons (self._step_buttons
in the code below, a list) and another attribute that stores the reference of the selected button (self._step_selected
in the code below).
The code could look like this:
import tkinter as tk
from functools import partial
class Popup2(tk.Toplevel):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.geometry("300x300")
self.title("Secondary")
self.entry_input = tk.StringVar()
tk.Label(self, text="Your input").pack()
tk.Entry(self, textvariable=self.entry_input).pack()
tk.Button(self, text="Submit", command=self.evaluation, bg="pink").pack()
def evaluation(self):
input_value = self.entry_input.get()
self.master.add_step(input_value)
self.destroy()
class Ldo(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self._step_buttons = []
self._step_selected = None
self.grid()
self.app_outline()
def app_outline(self):
self.masterframe1 = tk.Frame(self.master, width=300, height=300)
self.masterframe1.grid(sticky=tk.N, padx=20)
self.masterframe2 = tk.Frame(self.master, width=300, height=100)
self.masterframe2.grid(sticky=tk.S, padx=20)
self.addtabbutton = tk.Button(self.masterframe2, text="Add Step", width=10,
command=self.open_popup, bg="sienna1")
self.addtabbutton.grid(row=0, column=0, sticky=tk.EW)
self.runallbutton = tk.Button(self.masterframe2, text="Run All", width=10,
command=self.process_all, bg="sienna1", state=tk.DISABLED)
self.runallbutton.grid(row=0, column=1, sticky=tk.EW)
self.runselbutton = tk.Button(self.masterframe2, text="Run Selected", width=10,
command=self.process_selected, bg="sienna1", state=tk.DISABLED)
self.runselbutton.grid(row=0, column=2, sticky=tk.EW)
def open_popup(self):
Popup2(master=self)
def add_step(self, step):
btn = tk.Button(self.masterframe1, text=step, bg="light blue")
btn.configure(command=partial(self.select_button, btn))
btn.pack()
self._step_buttons.append(btn)
self.runallbutton.config(state=tk.NORMAL)
def select_button(self, button):
if self._step_selected == button:
self._step_selected.config(bg="light blue")
self._step_selected = None
self.runselbutton.config(state=tk.DISABLED)
else:
if self._step_selected:
self._step_selected.config(bg="light blue")
button.config(bg="white")
self._step_selected = button
self.runselbutton.config(state=tk.NORMAL)
def process_all(self):
print("Processing all: ")
for btn in self._step_buttons:
print(" Processing {}...".format(btn["text"]))
def process_selected(self):
print("Processing selected: ")
print(" Processing {}...".format(self._step_selected["text"]))
if __name__ == "__main__":
app = Ldo()
app.master.title("Primary")
app.mainloop()
I have modified other things, for example, I have provided a toggle button behavior for the buttons.
This is the result:
Upvotes: 1