3

Ive made a sample program on how generally it looks like.. my goal is to have the Data Entry write permanently to the button so dat if I run the program again its update the current price.

from tkinter import*
import tkinter as tk
import tkinter.simpledialog

def changeP1(event):
    btnT4=tk.Button(root,text='Updating...',width=10,bg='green')
    btnT4.grid(in_=root,row=1,column=2)
    btnT4.bind('<1>',changeP1)
    askC1=tk.simpledialog.askfloat('Updating...','What is the current price?')
    btnT4=tk.Button(root,text=('RM {:,.2f}'.format(askC1)),width=10)
    btnT4.grid(in_=root,row=1,column=2)
    btnT4.bind('<1>',changeP1)
def changeP2(event):
    btnT4=tk.Button(root,text='Updating...',width=10,bg='green')
    btnT4.grid(in_=root,row=2,column=2)
    btnT4.bind('<1>',changeP2)
    askC2=tk.simpledialog.askfloat('Updating...','What is the current price?')
    btnT4=tk.Button(root,text=('RM {:,.2f}'.format(askC2)),width=10)
    btnT4.grid(in_=root,row=2,column=2)
    btnT4.bind('<1>',changeP2)
def changeP3(event):
    btnT4=tk.Button(root,text='Updating...',width=10,bg='green')
    btnT4.grid(in_=root,row=3,column=2)
    btnT4.bind('<1>',changeP3)
    askC3=tk.simpledialog.askfloat('Updating...','What is the current price?')
    btnT4=tk.Button(root,text=('RM {:,.2f}'.format(askC3)),width=10)
    btnT4.grid(in_=root,row=3,column=2)
    btnT4.bind('<1>',changeP3)

root=Tk()
Title=['Item','Unit','Price']
Item=['Kopi O','Teh O','Teh Tarik']
Unit= '1 cup'
Price=[1,0.9,1.2]
cl=[0,1,2]
rw=[1,2,3]

for i in range(3):
    btnT1=tk.Button(root,text=Title[i],width=10,bg='yellow')
    btnT1.grid(in_=root,row=0,column=cl[i])

for x in range(3):
    btnT2=tk.Button(root,text=Item[x],width=10)
    btnT2.grid(in_=root,row=rw[x],column=0)

for y in range(3):
    btnT3=tk.Button(root,text=Unit,width=10)
    btnT3.grid(in_=root,row=rw[y],column=1)             

for z in range(3):
    btnT4=tk.Button(root,text=('RM {:,.2f}'.format(Price[z])),width=10)
    btnT4.grid(in_=root,row=rw[z],column=2)
    if z in range(0,1):
        btnT4.bind('<1>',changeP1)
    if z in range(1,2):
        btnT4.bind('<1>',changeP2)
    if z in range(2,3):
        btnT4.bind('<1>',changeP3)

root.mainloop()

and if theres anyway to make this simpler..

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • Have you tried StringVar? – Jonah Fleming Dec 14 '15 at 05:35
  • I'm very sorry but i have to say that this code is very poor… Did you know that buttons have a `command` attribute? eg. `Button(root, text="h", command=changeP3)` this means that you don't need to bind the command to it. Also you could just have one command to do the changing for all the buttons by passing the button to the command. For more help go to my website [here](https://pythonqanda.weebly.com). – Jonah Fleming Dec 14 '15 at 06:57

1 Answers1

2

You have 2 options (well that I know of) since you're dynamically creating your buttons. Both options only require one function.

If you wish to use bind then you can get the selected widget using event.widget

def onChange(event):
    ans = tk.simpledialog.askfloat('Updating...','What is the current price?')
    if ans: # checks if None is returned when clicking cancel
        event.widget.config(text='RM {:,.2f}'.format(ans))

And so in your loop you'd only have the one bind btnT4.bind('<1>', onChange).

Alternatively use the command attribute for the button to assign the function to be called when the button is pressed. Using command for the button is generally more pythonic than binding.

This requires you to also create a list to store the buttons, to allow the function to know which widget to change.

btn_list = [] # create an empty list for the buttons

# Your for loop will look like this the command parameter instead 
# and append the button to the list
for z in range(3):
    btnT4=tk.Button(root,text=('RM {:,.2f}'.format(Price[z])),width=10,\
                    command=lambda i=z: onChange(i))
    btnT4.grid(in_=root,row=rw[z],column=2)
    btn_list.append(btnT4)

lambda will pass the value of z into the onChange function to create a unique call for that button. The value of 'z' is relative to the index position of the button in the list.

The onChange function when called will ask for the new input, and if valid will update the button object stored in the list using the index.

# Your change function will look like this
def onChange(i):
    ans = tk.simpledialog.askfloat('Updating...','What is the current price?')
    if ans:
        btn_list[i].config(text='RM {:,.2f}'.format(ans))
Steven Summers
  • 5,079
  • 2
  • 20
  • 31