How to store button name, from a loop, when clicked on? - python-3.x

Trying to store the name of the buttons that are clicked on, in a list (orderList). These buttons were also generated from a list (menuList) by a FOR loop. Whenever any button is clicked, it stores the last value only.
menuList = ['egg', 'bacon', 'bread']
orderList = []
def makeOrder(arg):
orderList.append(arg)
print (orderList)
for btn in mealList:
ttk.Button(mainframe, text=btn, command=lambda: makeOrder(btn)).grid(column=1, row=5)
I just want to get each button to store it's name inside the blank list (orderList)

This is due to late binding of python which you can read more about it here. In short, you can work it out by modifying your lambda function:
from tkinter import ttk
import tkinter as tk
menuList = ['egg', 'bacon', 'bread']
mealList = ["breakfast","lunch","dinner"]
orderList = []
root = tk.Tk()
mainframe = tk.Frame(root)
mainframe.pack()
for num,btn in enumerate(mealList):
ttk.Button(mainframe, text=btn,command=lambda x=btn: orderList.append(x)).grid(column=num, row=5)
tk.Button(mainframe,text="result",command=lambda: print (orderList)).grid(row=6,column=0)
root.mainloop()

Related

Tkinter how update main window combobox values from Toplevel list python3.8

I have 3 modules (small, dont worry).
main_module = it has a combobox and a button. Comobobox list must be update each time a list (in module2) increases in number of names (combo values). Button calls the second window (module2)-->
myapp_second_window.py which has a entry box and another button. We write a name in the entry, push the button...voila..the list increases. In the origina app the list is created automatically when (2) is called.
Now I pass the list to a Pages.variable that is in -->
my_pages_to_connect_modules.
So, when app start I can populate combobox calling (2) to generate a Pages.variable list or populate combobox with json previously written.
The problem? --> how populate combobox while app is running. I mean, we go to (2) create a new name in entry come back to (1) and it is already there.
main_module
import tkinter as tk
from tkinter import*
from tkinter import ttk
import myapp_second_window
from myapp_second_window import SecondClass
root= Tk()
root.geometry("500x500")
root.title('myAPP_Main_Window')
class MainClass:
def __init__(self, parent,myapp_second_window):
self.parent = parent
self.my_widgets1()
def call_second_page (self):
Window2 = tk.Toplevel(root)
Window2.geometry('400x300')
myapp_second_window.SecondClass(Window2)
def my_widgets1(self):
self.field1_value = StringVar()
self.field1 = ttk.Combobox(self.parent, textvariable=self.field1_value)
self.field1['values'] = [1,2] # Pages.variable comes Here
self.field1.grid( row=0, column=0)
self.myButton = tk.Button(self.parent, text = "Call Second module", command = self.call_second_page)
self.myButton.grid(row=2, column=0)
if __name__ == '__main__':
app = MainClass(root, myapp_second_window)
root.mainloop()
myapp_second_window.py
import tkinter as tk
from tkinter import*
from tkinter import ttk
root= Tk()
root.minsize(550,450)
root.maxsize(560,460)
root.title('myAPP_Second_Window')
class SecondClass:
def init(self, parent):
self.parent = parent
self.my_widgets()
self.names = []
def my_widgets(self):
mylabel = Label(self.parent, text='Insert new name in next widget:')
mylabel.grid(column=0, row=0, sticky=W, pady=3)
button1 = tk.Button(self.parent, text="Click to enter Names in list", command=self.addToList)
button1.grid(column=3, row=0, sticky=W, pady=3)
self.name = StringVar()
valueEntry = tk.Entry(self.parent, textvariable= self.name)
valueEntry.grid(row=1, column=0, sticky=W, pady=3)
def addToList(self):
self.names.append(self.name.get())
print('listentries', self.names)
Pages.list_of_names = self.names
my_pages_to_connect_modules.
class Pages():
list_of_names = " "
It`s been challenging to me, every help is welcome. But please dont say just that I must update main window, I need to know how. Thanks to all of you.

tkinter buttons through a loop, how do i identify which was clicked?

I created a loop to create a button for each element in a list. How do I identify which button is clicked and then assign a command to each one, which will create a new page with the same name as the button clicked?.
yvalue = 200
for i in sdecks:
deckbutton1=Button(fcpage,text=i,width=21,bd=2,fg="ghost white",bg="orchid1")
deckbutton1.place(x=105, y=yvalue)
yvalue = yvalue + 20
Either I don't get you question or this (adapted from here) should answer your question:
from functools import partial
import tkinter as tk
def create_new_page(name_of_page):
print("Creating new page with name=\"%s\"" % name_of_page)
root = tk.Tk()
for i in range(5):
# Create the command using partial
command = partial(create_new_page, i)
button = tk.Button(root, text="Button number"+str(i+1), command=command)
button.pack()
root.mainloop()

How to use the event driven GUI menu's default value, before user starts his events in tkinter, Python?

I have one menu in my GUI. This menu is used to select which label will be added to the GUI.
When I start the program, the menu already shows the default option selected, but this option isn't used anywhere in the program. It requires user's action (click and select in menu) to get something out of that menu.
I want my program to immediately use the default menu's option, that later can be changed by the user.
Can you give me tips not only for this specific label-related task, but in general? How to use the default menu value in the program, without interaction with the menu?
This is my code:
from tkinter import *
root=Tk()
root.title("test")
# root.geometry("400x400")
def selected(event):
myLabel=Label(root, text=clicked.get()).pack()
options=["a","b","c"]
clicked = StringVar()
clicked.set(options[0])
drop=OptionMenu(root,clicked,*options, command=selected)
drop.pack()
root.mainloop()
An easy way:
from tkinter import *
root=Tk()
root.title("test")
# root.geometry("400x400")
def selected(event):
myLabel['text'] = clicked.get()
options=["a","b","c"]
clicked = StringVar()
clicked.set(options[0])
drop=OptionMenu(root,clicked,*options, command=selected)
drop.pack()
myLabel = Label(root, text=clicked.get())
myLabel.pack()
root.mainloop()
Or I suggested you use textvariable,then you needn't to use a function to change the label:
from tkinter import *
root=Tk()
root.title("test")
# root.geometry("400x400")
options=["a","b","c"]
clicked = StringVar()
clicked.set(options[0])
drop=OptionMenu(root,clicked,*options)
drop.pack()
myLabel = Label(root, textvariable=clicked) # bind a textvariable
myLabel.pack()
root.mainloop()

How to get input from a function in Python and print in tkinter GUI?

from tkinter import *
def printSomething():
inputValue=textBox.get("1.0","end-1c")
res=response(inputValue)
label = Label(root, text=res)
#this creates a new label to the GUI
label.pack()
root = Tk()
button = Button(root, text="Print Me", command=printSomething)
button.pack()
textBox=Text(root, height=2, width=10)
textBox.pack()
root.mainloop()
I have written a python code that returns text. and print that in tkinter label.while i try to execute it shows "None" in label.
It would probably be better to create the label in the global namespace once and then just update the label every time you press the button.
I also recommend using import tkinter as tk vs from tkinter import * as it provides better maintainability as your code grows and you do not end up overwriting built in methods.
I have updated your code and changed a few things to better fit the PEP8 standard.
import tkinter as tk
def print_something():
label.config(text=text_box.get("1.0", "end-1c"))
root = tk.Tk()
tk.Button(root, text="Print Me", command=print_something).pack()
text_box = tk.Text(root, height=2, width=10)
text_box.pack()
label = tk.Label(root)
label.pack()
root.mainloop()
Just changing your line:
res = response(inputValue)
to
res = inputValue
worked for me, creating a new label every time I pressed the button.

Dynamic Form Widget interaction in python tkinter

I am trying to generate a blank GUI, with 1 menu Item.
I then use a function to generate a label, a button and an entry widget on the same form when the selection is made from the menu item.
However when I try to use the get() method to get the value of the input in the generated textbox, I get an error. I may have missed some core concept here and this may not be possible, but I would like to know. Following is my code,
from tkinter import Tk, Label, Button, Entry, Menu
def btn_clientadd():
print(txt1.get())
def addclient():
lbl1 = Label(window, text="Client Name :")
lbl1.grid(row=1,column=1,padx=7,pady=7,sticky='e')
txt1 = Entry(window)
txt1.grid(row=1, column=2)
txt1.focus()
btn = Button(window, text="Add Client", command=btn_clientadd)
btn.grid(row=2,column=2,padx=7,pady=7)
window = Tk()
window.geometry('400x200')
menu = Menu(window)
new_item1 = Menu(menu)
menu.add_cascade(label='ClientMaster', menu=new_item1)
new_item1.add_command(label='Add New Client', command=addclient)
window.config(menu=menu)
window.mainloop()
The entry txt1 is created inside a function and the reference to it is garbage collected when the function ends. One way you can get around this it to declare a StringVar() in the global scope and then associate it to the entry.
Examine the example below:
from tkinter import Tk, Label, Button, Entry, Menu, StringVar
def btn_clientadd():
print(client_string.get()) # Get contents of StringVar
def addclient():
lbl1 = Label(window, text="Client Name :")
lbl1.grid(row=1,column=1,padx=7,pady=7,sticky='e')
# Create entry and associate it with a textvariable
txt1 = Entry(window, textvariable=client_string)
txt1.grid(row=1, column=2)
txt1.focus()
btn = Button(window, text="Add Client", command=btn_clientadd)
btn.grid(row=2,column=2,padx=7,pady=7)
window = Tk()
window.geometry('400x200')
menu = Menu(window)
new_item1 = Menu(menu)
menu.add_cascade(label='ClientMaster', menu=new_item1)
new_item1.add_command(label='Add New Client', command=addclient)
window.config(menu=menu)
client_string = StringVar() # StringVar to associate with entry
window.mainloop()

Resources