How to sum a Treeview's values in Tkinter - python

I'm developing a GUI where the idea is to add some values to a treeview (as a billing system) and then get the result or sum of all items' prices.
The button "Agregar" (Add in English) get the Entries' data and add them to the treevew; one of them if the amount of money to pay.
Now what I want, and haven't been able to get, is the sum of the values given in the treeview to be shown in the field or entry which is below the treeview when "Generar" (Generate in English) button is pressed.
Next, the code I got:
#!/usr/bin/python
#-*- coding:utf-8 -*-
from Tkinter import*
from ttk import Combobox, Treeview
from tkMessageBox import*
import MySQLdb
from controller import *
import math
class Gastos(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
#INSTANCIAS
global cc, nombre, pago, ref, cod, desc, valor
#INSTANCIAS DE LOS WIDGETS
global e1, e2, e3, e4, e5, tree, l8
cc = IntVar()
nombre = StringVar()
pago = StringVar()
ref = StringVar()
cod = StringVar()
desc = StringVar()
valor = DoubleVar()
tbancos = ['Bancolombia', "Banco Bogotá", "Banco Agrario", "Banco Occidente"]
lupa = PhotoImage(file='img/lupa.png')
tbanktype = ['Corriente','Ahorro']
fpago = ['Efectivo','Transferencia']
resultado = DoubleVar()
#BUSQUEDA = ["Nombre","CC/Nit"]
busqueda = StringVar()
busqueda.trace("w", lambda name, index, mode: buscar())
dato = StringVar()
#WIDGETS
#========================= HEADER ==============================
self.titleL = Label(self, text="GASTOS", font="bold")
self.titleL.pack(pady=20, side=TOP)
#========================== WRAPPER ============================
self.wrapper = Frame (self)
self.wrapper.pack(side=LEFT, fill=Y)
#Esto centro el wrapper
#self.wrapper.pack(side=LEFT, fill=BOTH, expand=True)
#======================== BENEFICIARIO =======================
self.lf1 = LabelFrame(self.wrapper, text="Beneficiario")
self.lf1.pack(fill=X, ipady=5)
self.f0 = Frame(self.lf1)
self.f0.pack(pady=5, fill=X)#-----------------------------------
l1 = Label(self.f0, text='CC/Nit:')
l1.pack(side=LEFT)
e1 = Entry(self.f0, textvariable=cc)
e1.pack(side=LEFT)
b0 = Button(self.f0, text='Buscar:', image=lupa, command=buscarB)
b0.pack(side=LEFT)
l2 = Label(self.f0, text='Nombre:')
l2.pack(side=LEFT)
e2 = Entry(self.f0, textvariable=nombre)
e2.pack(side=LEFT, fill=X, expand=1)
self.f1 = Frame(self.lf1)
self.f1.pack(pady=5, fill=X)#-----------------------------------
l3 = Label(self.f1, text='Forma de Pago:')
l3.pack(side=LEFT)
Cbx = Combobox(self.f1, textvariable=pago, values=fpago, width=15)
Cbx.set('Efectivo')
Cbx.pack(side=LEFT)
l4 = Label(self.f1, text='Ref. Bancaria:')
l4.pack(side=LEFT)
e3 = Entry(self.f1, textvariable=ref)
e3.pack(side=LEFT, fill=X, expand=1)
b1 = Button(self.f1, text='Buscar:', image=lupa)
b1.image=lupa
b1.pack(side=LEFT)
#======================== CONCEPTO ========================
self.lf2 = LabelFrame(self.wrapper, text="Concepto")
self.lf2.pack(fill=X, ipady=5)
self.f2 = Frame(self.lf2)
self.f2.pack(pady=5, fill=X)#-------------------------------
l5 = Label(self.f2, text='Código:')
l5.pack(side=LEFT)
e4 = Entry(self.f2, textvariable=cod)
e4.pack(side=LEFT)
b2 = Button(self.f2, text='Buscar:', image=lupa, command=buscarC)
b2.pack(side=LEFT)
self.f3 = Frame(self.lf2)
self.f3.pack(pady=5, fill=X)#-------------------------------
l6 = Label(self.f3, text='Descripción:')
l6.pack(side=LEFT)
e5 = Entry(self.f3, textvariable=desc, state=DISABLED)
e5.pack(side=LEFT, fill=X, expand=1)
l7 = Label(self.f3, text='Valor:')
l7.pack(side=LEFT)
e6 = Entry(self.f3, width=15, textvariable=valor)
e6.pack(side=LEFT)
b3 = Button(self.f3, text='Agregar:', command=agregar)
b3.pack(side=LEFT)
#-------------------------- TREEVIEW ---------------------------
self.f4 = Frame(self.wrapper)
self.f4.pack(pady=5,fill=X)
tree = Treeview(self.f4, height=4, show="headings", columns=('col1','col2','col3'))
tree.pack(side=LEFT, fill=X, expand=1)
tree.column('col1', width=20, anchor='center')
tree.column('col2', width=200, anchor='center')
tree.column('col3', width=10, anchor='center')
tree.heading('col1', text='Código')
tree.heading('col2', text='Concepto')
tree.heading('col3', text='Valor')
scroll = Scrollbar(self.f4,orient=VERTICAL,command=tree.yview)
tree.configure(yscrollcommand=scroll.set)
#--------------------------------------------------------------
self.f5 = Frame(self.wrapper)
self.f5.pack(pady=5,fill=X)#-------------------
#RESULT MUST BE SHOWN HERE
l8 = Label(self.f5, text=resultado, fg="red", bg="white", anchor='e', font="bold, 22", relief= SUNKEN)
l8.pack(fill=X, side=RIGHT, expand=1)
#l8.set("link")
self.fBtn = Frame(self.wrapper)
self.fBtn.pack()#-------------------------------
clean = Button(self.fBtn, text='Cancelar', bg='navy', foreground='white', activebackground='red3', activeforeground='white', command=limpiar)
clean.pack(side=RIGHT)
update = Button(self.fBtn, text='Actualizar', bg='navy', foreground='white', activebackground='red3', activeforeground='white', state=DISABLED)
update.pack(side=RIGHT)
add = Button(self.fBtn, text='Generar', bg='navy', foreground='white', activebackground='red3', activeforeground='white', command=generar)
add.pack(side=RIGHT)
#========================= ASIDE ===========================
self.aside = Frame(self)
self.aside.pack(side=TOP, fill=BOTH)
self.wrap1 = Frame(self.aside)
self.wrap1.pack()
self.viewer = Label(self.wrap1, text="LISTA DE GASTOS")
self.viewer.pack()
scroll = Scrollbar(self.wrap1, orient=VERTICAL)
scroll.pack(side=RIGHT, fill=Y)
lb = Listbox(self.wrap1, yscrollcommand=scroll.set, height=20, width=30)
scroll.config (command=lb.yview)
lb.pack(fill=BOTH)
lb.bind("<Double-Button-1>", callback)
self.wrap2 = Frame(self.aside)
self.wrap2.pack()
load = Button(self.wrap2, text='Cargar lista', bg='navy', foreground='white', activebackground='red3', activeforeground='white', command=cargar_lista)
load.pack(fill=X)
delete = Button(self.wrap2, text='Borrar', bg='navy', foreground='white', activebackground='red3', activeforeground='white', command=borrar)
delete.pack(fill=X)
edit = Button(self.wrap2, text='Modificar', bg='navy', foreground='white', activebackground='red3', activeforeground='white', command=modificar)
edit.pack(fill=X)
buscador = Label(self.wrap2, text="Buscar por Número:")
buscador.pack()
E = Entry(self.wrap2, textvariable=busqueda, width=24)
E.pack()
E.bind("<KeyRelease>", caps)
def cargar_lista():
try:
connect.commit()
display = "SELECT g_num FROM detalles order by g_num;"
cursor.execute(display)
registros = cursor.fetchall()
lb.delete(0, END)
for item in registros:
#print item
num = item[0]
lb.insert(END, num)
except:
showerror("Mensaje", "Ha ocurrido un error")
# NUEVO / CANCELAR
def limpiar():
tree.delete(*tree.get_children())
pass
def agregar():
v1 = cc.get()
v2 = None
v3 = cod.get()
v4 = desc.get()
v5 = valor.get()
tree.insert('', 0, values=(v3,v4,v5))
#FUNCTION THAT GIVE THE VALUES
def generar():
children = tree.get_children()#OBTIENE LOS iid DE LOS ITEMS
for child in children:
i = tree.item(child, 'values')[2]#OBTIENE LOS VALORES DE LOS ITEMS
print i
def borrar():
pass
def bloquear():
pass
def callback(event):
llenar_campos()
def llenar_campos():
pass
def habilitar():
pass
def modificar():
pass
def actualizar():
pass
def buscar():
pass
def buscarB():
connect.commit()
try:
v = cc.get()
sql = "SELECT b_nombre from beneficiarios WHERE b_cc='%d';" % (v)
cursor.execute(sql)
query = cursor.fetchone()
for n in query:
nombre.set(n)
except TypeError, e:
showerror("Error", e)
except MySQLdb.IntegrityError, e:
showerror("Error", e)
def buscarC():
connect.commit()
try:
v = cod.get()
sql = "SELECT cg_nombre from concepto_gastos WHERE cg_cod='%s';" % (v)
cursor.execute(sql)
query = cursor.fetchone()
for n in query:
desc.set(n)
except TypeError, e:
showerror("Error", e)
except MySQLdb.IntegrityError, e:
showerror("Error", e)
except:
showerror ("Mensaje", "No se encuentra!")
# CONVIERTE LA ENTRADA DE LOS ENTRIES EN MAYÚSCULA
def caps(event):
pass
The code is not finished, that's why it has so much info. But next function is what give me the values I need to be sum:
def generar():
children = tree.get_children()#OBTIENE LOS iid DE LOS ITEMS
for child in children:
i = tree.item(child, 'values')[2]#OBTIENE LOS VALORES DE LOS ITEMS
print i
By the way, this file is called by another (home.py) to interact with it.
If anyone could give me a hand this problem, you'll save a life. Thanks for your time, look on this, and anything you could answer. Sorry for my English if it is not good.

You have to convert string to float and then you can add to variable ie. total
def generar():
total = 0.0
for child in tree.get_children():
total += float(tree.item(child, 'values')[2])
print total
But you could add value even in agregar to get total with using button
# create global variables
total = 0.0
# or
total_var = DoubleVar()
def agregar():
# inform function to use external/global variable when you use `+=`
global total
v1 = cc.get()
v2 = None
v3 = cod.get()
v4 = desc.get()
v5 = valor.get()
total += v5
# or
total_var.set(total_var.get() + v5)
tree.insert('', 0, values=(v3,v4,v5))
Full working example
import Tkinter as tk
import ttk
# --- functions ---
def agregar(v3, v4, v5):
tree.insert('', 0, values=(v3,v4,v5))
def generar():
total = 0.0
for child in tree.get_children():
total += float(tree.item(child, 'values')[2])
print total
result['text'] = 'Total: {}'.format(total)
# --- main ---
root = tk.Tk()
tree = ttk.Treeview(root, height=4, show="headings", columns=('col1','col2','col3'))
tree.pack()
tree.heading('col1', text='Código')
tree.heading('col2', text='Concepto')
tree.heading('col3', text='Valor')
add = tk.Button(root, text='Generar', command=generar)
add.pack()
result = tk.Label(root, text='Total: 0')
result.pack()
agregar("1", "AAA", 1.11)
agregar("2", "BBB", 2.22)
agregar("3", "CCC", 3.33)
root.mainloop()

The reason you are getting PY_VAR240 is because your code is trying to display an object instead of a value.
There is already an answer here that hints at the issue as well: Python Tkinter Treeview - Iterating 'get_children' output
Also here is how I get the values from a row:
rowItem = treeSomeTree.item(itemID)
itemDictionary = rowItem['values']
someVariable = itemDictionary[0]
Note the item id variable represents row item identifier which may or may not be a number and must be unique. The treeview .insert defaults to None (iid=None) if not specified.
By specifying the iid as an integer value as you inert rows you will always know which row you have (or need to get) to summarize.

Related

Python GUI App is not functioning well, help me fix it?

Here's my code of a gui app using tkinter library, it creats tables and prints orders for each table and gives the ability to edit orders on every table. the goal of it to know what did each table order. but editing the orders doesn't seem to work at all, I need help fixing it.
import tkinter as tk
class TableOrdersApp:
def __init__(self, master):
self.tables = []
self.table_list = tk.Listbox(master)
self.table_list.pack(side=tk.LEFT, fill=tk.BOTH)
self.table_list.bind("<<ListboxSelect>>", self.refresh_label)
self.orders_label = tk.Label(master, text="", anchor=tk.W, justify=tk.LEFT, wraplength=400)
self.orders_label.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.button_frame = tk.Frame(master)
self.button_frame.pack(side=tk.RIGHT)
self.add_button = tk.Button(self.button_frame, text="Add Table", command=self.add_table)
self.add_button.pack(side=tk.TOP)
self.remove_button = tk.Button(self.button_frame, text="Remove Table", command=self.remove_table)
self.remove_button.pack(side=tk.TOP)
self.edit_button = tk.Button(self.button_frame, text="Edit Order", command=self.edit_order)
self.edit_button.pack(side=tk.TOP)
self.remove_order_button = tk.Button(self.button_frame, text="Remove Order", command=self.remove_order)
self.remove_order_button.pack(side=tk.TOP)
def add_table(self):
self.tables.append([])
self.table_list.insert(tk.END, "Table {}".format(len(self.tables)))
def remove_table(self):
index = self.table_list.curselection()[0]
self.tables.pop(index)
self.table_list.delete(index)
def refresh_label(self, event=None):
self.orders_label.config(text="\n".join(self.tables[self.table_list.curselection()[0]]))
def edit_order(self):
index = self.table_list.curselection()[0]
orders = self.tables[index]
if self.orders_label.select_present():
start_index = self.orders_label.index(tk.SEL_FIRST)
end_index = self.orders_label.index(tk.SEL_LAST)
selected_text = self.orders_label.selection_get()
num_newlines = selected_text.count("\n")
order_index = start_index.split(".")[0] - 1 - num_newlines
new_order = tk.simpledialog.askstring("Edit Order", "Enter the new order:")
orders[order_index] = new_order
self.refresh_label()
def remove_order(self):
index = self.table_list.curselection()[0]
orders = self.tables[index]
start_index = self.orders_label.index(tk.SEL_FIRST)
end_index = self.orders_label.index(tk.SEL_LAST)
num_newlines = self.orders_label.get(start_index, end_index).count("\n")
order_index = start_index.split(".")[0] - 1 - num_newlines
orders.pop(order_index)
self.refresh_label()
# Create the main window
root = tk.Tk()
# Create an instance of the TableOrdersApp class
app = TableOrdersApp(root)
# Run the main loop of the app
root.mainloop()
I tried to make it print a label and make it editable using "edit order" button, but the button itself doesn't seem to work, and I want it to print "Empty" if the table has no orders how can i do that.
Look in edit_order and remove_order function. Must easier to write less coding.
Here is code:
import tkinter as tk
class TableOrdersApp:
def __init__(self, master):
self.tables = []
self.table_list = tk.Listbox(master)
self.table_list.pack(side=tk.LEFT, fill=tk.BOTH)
self.table_list.bind("<<ListboxSelect>>", self.refresh_label)
self.orders_label = tk.Label(master, text="", anchor=tk.W, justify=tk.LEFT, wraplength=400)
self.orders_label.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.button_frame = tk.Frame(master)
self.button_frame.pack(side=tk.RIGHT)
self.add_button = tk.Button(self.button_frame, text="Add Table", command=self.add_table)
self.add_button.pack(side=tk.TOP)
self.remove_button = tk.Button(self.button_frame, text="Remove Table", command=self.remove_table)
self.remove_button.pack(side=tk.TOP)
self.edit_button = tk.Button(self.button_frame, text="Edit Order", command=self.edit_order)
self.edit_button.pack(side=tk.TOP)
self.remove_order_button = tk.Button(self.button_frame, text="Remove Order", command=self.remove_order)
self.remove_order_button.pack(side=tk.TOP)
def add_table(self):
self.tables.append([])
self.table_list.insert(tk.END, "Table {}".format(len(self.tables)))
def remove_table(self):
index = self.table_list.curselection()[0]
self.tables.pop(index)
self.table_list.delete(index)
def refresh_label(self, event=None):
self.orders_label.config(text="\n".join(self.tables[self.table_list.curselection()[0]]))
def edit_order(self):
index = self.table_list.curselection()[0]
orders = self.table_list.get(index)
print(index)
order = orders
self.orders_label.configure(text=order)
#if self.orders_label.select_present():
#start_index = self.orders_label.index(tk.SEL_FIRST)
#end_index = self.orders_label.index(tk.SEL_LAST)
#selected_text = self.orders_label.selection_get()
#num_newlines = selected_text.count("\n")
#order_index = start_index.split(".")[0] - 1 - num_newlines
#new_order = tk.simpledialog.askstring("Edit Order", "Enter the new order:")
#orders[order_index] = new_order
#self.refresh_label()
def remove_order(self):
remove_orders = self.table_list.curselection()
self.table_list.delete(remove_orders)
self.orders_label.configure(text="")
#index = self.table_list.curselection()[0]
#orders = self.tables[index]
#start_index = self.orders_label.index(tk.SEL_FIRST)
#end_index = self.orders_label.index(tk.SEL_LAST)
#num_newlines = self.orders_label.get(start_index, end_index).count("\n")
#order_index = start_index.split(".")[0] - 1 - num_newlines
#orders.pop(order_index)
#self.refresh_label()
# Create the main window
root = tk.Tk()
# Create an instance of the TableOrdersApp class
app = TableOrdersApp(root)
# Run the main loop of the app
root.mainloop()
Result when executes:
Result when selected:
Result when removed order:

How to constantly update a variable (using a spinbox with tkinter)?

I have in my program two spinboxes, created with tkinter. I want the variables chosen by the user to be added to a list, so I can use those values later in the program. The problem I'm currently having is that the values are stored just once in the list, and I don't manage to update them, despite all of the things I tried. To be clear, I just want two values in the list, so when the user select another number, it will replace the proper value stored in the list.
Here is the code I wrote :
from tkinter import *
windowTk = Tk()
pwMain = PanedWindow(windowTk, orient=VERTICAL)
pwTop = PanedWindow(pwMain, orient=HORIZONTAL)
def configTables() :
sLine = Spinbox(pwTop, from_=0, to=15)
pwTop.add( Label(pwTop, text = "Combien y a-t-il de lignes de table ?") )
pwTop.add( sLine )
sColumn = Spinbox(pwTop, from_=0, to=15)
pwTop.add( Label(pwTop, text = "Combien y a-t-il de colonnes de tables ?") )
pwTop.add( sColumn )
pwTop.pack()
pwMain.pack()
global coordTables
coordTables = []
coordTables.append( int(sLine.get()) )
coordTables.append( int(sColumn.get()) )
return coordTables
print( configTables() )
windowTk.mainloop()
I hope my request is understandable, so you can help me.
Thank you
LoneRetrievr
UPDATE : I tried the following code, and it works, but nothing appears in the window (tkinter's window remains white).
from tkinter import *
windowTk = Tk()
pwMain = PanedWindow(windowTk, orient=VERTICAL)
pwTop = PanedWindow(pwMain, orient=HORIZONTAL)
lines = IntVar(windowTk, value=0)
columns = IntVar(windowTk, value=0)
def configTables() :
sLine = Spinbox(pwTop, from_=0, to=15, textvariable=lines)
pwTop.add( Label(pwTop, text = "Combien y a-t-il de lignes de tables ?") )
pwTop.add( sLine )
sColumn = Spinbox(pwTop, from_=0, to=15, textvariable=columns)
pwTop.add( Label(pwTop, text = "Combien y a-t-il de colonnes de tables ?") )
pwTop.add( sColumn )
pwTop.pack()
pwMain.pack()
numberLines = lines.get()
numberColumns = columns.get()
print( numberLines, numberColumns )
windowTk.mainloop()
I know it will print just once the values and that's what I want it to do.
Can you help me ? I think it's very simple, but I don't find where's the problem.
You can use IntVar to connect the spin boxes to Python variables. I have extended your program with an example. It adds a button to print the current value of the spin boxes:
from tkinter import *
windowTk = Tk()
pwMain = PanedWindow(windowTk, orient=VERTICAL)
pwTop = PanedWindow(pwMain, orient=HORIZONTAL)
lignes = IntVar(windowTk, value=0)
colonnes = IntVar(windowTk, value=0)
def print_vars():
print(lignes.get(), colonnes.get())
def configTables() :
sLine = Spinbox(pwTop, from_=0, to=15, textvariable=lignes)
pwTop.add( Label(pwTop, text = "Combien y a-t-il de lignes de table ?") )
pwTop.add( sLine )
sColumn = Spinbox(pwTop, from_=0, to=15, textvariable=colonnes)
pwTop.add( Label(pwTop, text = "Combien y a-t-il de colonnes de tables ?") )
pwTop.add( sColumn )
pwTop.pack()
b = Button(pwMain, text='print', command=print_vars)
b.pack(side=BOTTOM)
pwMain.pack()
global coordTables
coordTables = []
coordTables.append( int(sLine.get()) )
coordTables.append( int(sColumn.get()) )
return coordTables
print( configTables() )
windowTk.mainloop()
Note, I have not removed things which are no longer necessary, like coordTables variable and the return statement.
this is what you would want to do, I believe.
I suggest you an object oriented approach.
Tkinter has IntVar() and other variables very powerfull.
import tkinter as tk
class App(tk.Frame):
def __init__(self,):
super().__init__()
self.master.title("Hello World")
self.lines = tk.IntVar()
self.columns = tk.IntVar()
self.coordTables = []
self.init_ui()
def init_ui(self):
self.pack(fill=tk.BOTH, expand=1,)
f = tk.Frame()
tk.Label(f, text = "Combien y a-t-il de lignes de tables ?").pack()
tk.Spinbox(f, from_=0, to=15, textvariable= self.lines).pack()
tk.Label(f, text = "Combien y a-t-il de colonnes de tables ?").pack()
tk.Spinbox(f, from_=0, to=15, textvariable= self.columns).pack()
w = tk.Frame()
tk.Button(w, text="Print", command=self.on_callback).pack()
tk.Button(w, text="Reset", command=self.on_reset).pack()
tk.Button(w, text="Close", command=self.on_close).pack()
f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)
def on_callback(self,):
args = (self.lines.get(),self.columns.get())
self.coordTables.append(args)
print ("Numers of coords: {0}".format(len(self.coordTables)))
for e,i in self.coordTables:
print(e,i)
def on_reset(self):
self.lines.set(0)
self.columns.set(0)
self.coordTables = []
def on_close(self):
self.master.destroy()
if name == 'main':
app = App()
app.mainloop()

tkinter mutliplying the price from table

I am making a simple program for cafe management system that reads food names as a buttons from a table also I want to read the the food price from the table and multiply it by the number of button clicks and then save them into a Text how I can do this please
this is the image that show where are the two main isues are
from tkinter import *
from tkinter import ttk
import sqlite3
import time
import datetime
import random
variable = 1
bttn_clicks=0
button_dict = {}
button_dic = {}
conn = sqlite3.connect('hoteldb.db')
c = conn.cursor()
def showqurec():
global button,data2
data2 = readqurec()
for index, dat in enumerate(data2):
button= ttk.Button(master, text=dat[0],command=lambda dat=dat:update_count(dat))
button.grid(row=index+1, column=0,padx=0, pady=0)
button_dict[dat] = button
def showqado():
global button,data2
data2 = readqado()
for index, dat in enumerate(data2):
button = ttk.Button(master, text=dat[0],command=lambda dat=dat: update_count(dat))
button.grid(row=index+1, column=1,pady=0,padx=0)
button_dict[dat] = button
def showcasho():
global button,data2
data2 = readcasho()
for index, dat in enumerate(data2):
button=ttk.Button(master, text=dat[0],command=lambda dat=dat:update_count(dat))
button.grid(row=index+1, column=2,padx=0, pady=0)
button_dict[dat] = button
def readfromdatabase():
cur.execute("SELECT qureec.name,qado.name,casho.name FROM qureec,qado,casho")
return cur.fetchall()
def readqurec():
cur.execute("SELECT name FROM qureec ")
return cur.fetchall()
def readqado():
cur.execute("SELECT name FROM qado ")
return cur.fetchall()
def readcasho():
cur.execute("SELECT name FROM casho ")
return cur.fetchall()
def update_count(x):
global bttn_clicks,my_text,price
my_text=StringVar()
for name in data2:
my_text = button_dict[x].cget('text')
bttn_clicks += 1
def Receipt():
txtReceipt.delete("1.0", "4.0")
x = random.randint(10908, 500876)
randomRef = str(x)
Receipt_Ref.set("BILL" + randomRef)
txtReceipt.insert("1.0", 'Receipt Ref: \t\t\t'+Receipt_Ref.get()+"\t\t"+DateofOrder.get()+"\n")
txtReceipt.insert("2.0", 'Items\t\t'+'Quantity\t\t\t'+"Price \n\n")
if variable !=0:
txtReceipt.insert(END, str(my_text)+'\t\t'+str(bttn_clicks)+'\t\t\t'+""+str(bttn_clicks*3)+"\n")
master=Tk()
master.geometry('630x350+100+200')
master.title('Records')
Label = Button(master, text="meal", width=10,command=showqurec)
Label.grid(row=0, column=0)
BMILabel = Button(master, text="tea", width=10,command=showqado)
BMILabel.grid(row=0, column=1)
stateLabel = Button(master, text="fast food", width=10,command=showcasho)
stateLabel.grid(row=0, column=2)
lblReceipt = Button(master,text="Get Receipt:",anchor='w',command=Receipt)
lblReceipt.grid(row=0,column=4,sticky=W)
txtReceipt = Text(master,bg="white",width=47,height=17.5)
txtReceipt.grid(row=1,column=4,rowspan=4,columnspan=40)
Receipt_Ref=StringVar()
DateofOrder = StringVar()
master.mainloop()
Now I declared the prices but how I can get them from database
I also have another of buttons clicks are incrementing on every buttons clicked how on specied button
Getting the name on the buttons instead of just the first letter you have to set the name to the whole string, not just the first position:
button = ttk.Button(master, text=dat, command ...
(instead of dat[0])
for each of the categories: meal, tea and fast food.
I'm not getting a clear picture of how you want this to work in the end. Do you want the receipt to be updated for each product or only in the end. The function update_count() looks very strange.
I would recommend using a dict to store products and prices. This will make price lookup easy. As long as the application if fairly small I think a global variable would be preferrable.
products = {'Soup': 2.40, 'Fish': 3.10, 'Beef': 3.55, 'Pizza': 2.70}
Take a look at the example code below, try to run it and think about how you want the rest to work. Should the receipt be updated each time you push a button? Should the receipt be ordered in any way? What if you want to remove something from the receitp?
from tkinter import *
from tkinter import ttk
#import sqlite3
import time
import datetime
import random
variable = 1
bttn_clicks=0
button_dict = {}
button_dic = {}
#conn = sqlite3.connect('hoteldb.db')
#c = conn.cursor()
products = {} # Dictionary of products and prices
tally = [] # List of ordered products
def showqurec():
global button, data2
data2 = readqurec()
for index, dat in enumerate(data2):
button = ttk.Button(master, text=dat, command=lambda dat=dat: update_count(dat))
button.grid(row=index+1, column=0, padx=0, pady=0)
button_dict[dat] = button
def showqado():
global button, data2
data2 = readqado()
for index, dat in enumerate(data2):
button = ttk.Button(master, text=dat, command=lambda dat=dat: update_count(dat))
button.grid(row=index+1, column=1, pady=0, padx=0)
button_dict[dat] = button
def showcasho():
global button, data2
data2 = readcasho()
for index, dat in enumerate(data2):
button = ttk.Button(master, text=dat, command=lambda dat=dat: update_count(dat))
button.grid(row=index+1, column=2,padx=0, pady=0)
button_dict[dat] = button
def readfromdatabase(): # This function is never called...
return None
def readqurec(): # Get Meal from database
meal = {'Soup': 2.40, 'Fish': 3.10, 'Beef': 3.55, 'Pizza': 2.70}
products.update(meal)
return meal
def readqado(): # Get Tea from database
tea = {'Tea': 1.20, 'Coffee': 1.00, 'Soda': 1.65}
products.update(tea)
return tea
def readcasho(): # Get Fast food from database
fast_food = {'Hamburger': 1.80,'Hot dog': 1.45,'Pasta': 1.65}
products.update(fast_food)
return fast_food
def update_count(x):
global bttn_clicks,my_text,price
purchase = [x,products[x]] # Get the product and price
tally.append(purchase) # Add this purchase to the tally
print(purchase)
# Leaving the rest of the function as is ...
my_text=StringVar()
for name in data2:
my_text = button_dict[x].cget('text')
bttn_clicks += 1
def Receipt():
txtReceipt.delete("1.0", "4.0")
x = random.randint(10908, 500876)
randomRef = str(x)
Receipt_Ref.set("BILL" + randomRef)
txtReceipt.insert("1.0", 'Receipt Ref: \t\t\t'+Receipt_Ref.get()+"\t\t"+DateofOrder.get()+"\n")
txtReceipt.insert("2.0", 'Items\t\t'+'Quantity\t\t\t'+"Price \n\n")
if variable !=0:
txtReceipt.insert(END, str(my_text)+'\t\t'+str(bttn_clicks)+'\t\t\t'+""+str(bttn_clicks*3)+"\n")
master=Tk()
master.geometry('630x350+100+200')
master.title('Records')
Label = Button(master, text="meal", width=10,command=showqurec)
Label.grid(row=0, column=0)
BMILabel = Button(master, text="tea", width=10,command=showqado)
BMILabel.grid(row=0, column=1)
stateLabel = Button(master, text="fast food", width=10,command=showcasho)
stateLabel.grid(row=0, column=2)
lblReceipt = Button(master,text="Get Receipt:",anchor='w',command=Receipt)
lblReceipt.grid(row=0,column=4,sticky=W)
txtReceipt = Text(master,bg="white",width=47,height=17.5)
txtReceipt.grid(row=1,column=4,rowspan=4,columnspan=40)
Receipt_Ref=StringVar()
DateofOrder = StringVar()
master.mainloop()

tkinter labels dont show

So I got the assignment to make a small Bingo App (Windows btw) after I followed a few webinars on Tkinter GUI and some Googling.
I have made successfull little apps that worked correctly, but this time I try to make it with knowledge I think I have.
Anyway, in that Bingo app, I want 50 labels that represent 50 numbers of the Bingo card, 5 rows of 10 numbers.
I know how to align them, but they need to show up first.
Can you look at my code and assess what I do wrong?
Ignore the many Dutch comments :)
'''
iWMMMM0.
XM#o:..iIMM.
MM. :XC17, YM8
M# v#9. .W# ,M,
#M 7#i ,0$: M0 MM
.M. #7 M#t, ME MQ
MM iM. #$Ci$Q ;M#CCY:.
CM ,M, b#$; v;7IEW#MMM#1
MQ WQ .tE0Q2nCCYc;i,:7#MMi
:M #b . .. .:YCb0U: YMM.
WM E#i .... ,i: ,b#; bMQ,SbW06i
oM MC ... MME9#$Y . .#b SM#b2tob#MM1
Mi #7 ... #M .v iMt ... #X :CoUzt: :MM, nWM#Bc :nQ#$Ui
M: #Y .. M9 MM# b# ... Zb1#Zi. .;Z#Y SMi MM#t;vCMM,CMM0C77bMM8
M, #7 .. #6 Y7 ;Mn ... #QB. ,#b ZM MM .n9U; bMM. ;z2U7 MM
M: #Y ., #9.;tQQv ... ;MQ, :#; Mv MM X$: M; , ;$2. 7#i M8
M: #7 .. #BW1i ..,:Y$Mt$ MX MMtiEM: E#: ZME,.W$c ; c# .M
M: #Y ., ME .. .ZMM8o89 QM. i;U## .Zb7: ,BBYzQ bM# Mi M
Mi #X .. M, iMM#WS :bWQb, ,#M1;IoIX 1#c bMMX iM I#E$CM M, M
.MM #7 ., Mn EM8AEE#: . v$AWQ#$Q#MMIWz, ;$Z$ MMzW2 M# $ZY$C bM CM
MZ ib#i .. ##. ;t $z#. ., CWUWnE$b7: :Y #$c MEYY .MM8 :; vM. M1
iM iMi .., #bWI,..M#i#C .., Mv i#E. UMM2 #BC oC;tMMCES .#M MM
MY E0 ... S#i:Z$MZ .Mv ... M8 7WEz MnZo #obUA: ic.7bEW$#M#C iMM
CMi I#; .. b#; $$ ... ,MQ 7$Zz #zbz #IXW#E69z. 80 ::iAMM;
iM$ .$Qi . :Z$Q0Q#6. ... MQ0 C$b1 MtQ7 YZWW,.c$## MC MMM#b.
MM7 iBWv. .., .M#7$ v$8; vQ0:iCAM: :#bM0 nMU BM
:MM1 .6$Q7: ;MMS:Q7 ##i12EMzEESB# .7:,,2M# MM
,MM#: ,1E$BQbZ6EBMM#; iQQ##B$72n7i.,vo tQQIZQ$WC .#MQ
6MM#o;,,:ivY;i,,iEMM...,,:iC2Q#MMMQ$M$..,i::,;9MMZ
YIEbEAU269086, ;Bb08bAz;:. 7QbEZb8boi
'''
##Basale geimporteerde functies
from tkinter import*
#self=()
#Importeert de randomfucntie
#import random
#Importeert de Python Debugger
#Runnen met pdb.run
#import pdb
#Importeert de PIL Python Image Library
#from PIL import Image, ImageTK
#image = image.open("bestandsnaam.jpg")
#photo ImageTK.PhotoImage(image)
#Een afbeelding op een label
#label = Label(image=photo(als photo de naam van de variable is))
#label.image = photo (bewaren als referentie?<- geen idee nog)
'''
#=# Start van metainfo class/klasse
class MetaBingPy():
def __init__(self):
super(MetaBingPy, self).__init__()
self.parent = parent
self.pack()
MetaBingPy.BingoPyC(self)
##Functie voor random number generator
def BingoPyC:
self.root = Tk()
self.root.title("Python Bingo")
#=#Einde metainfo class
'''
###def random.randint(1,50)
#####of# randrange(1,50)
##GUI voor BingPy, moet root heten. Geen eigen naam, zoals:
##BingPyGUI wat ik had.
root = Tk()
root.wm_title("Bingo Python")
root.wm_maxsize("800","600")
root.wm_minsize("800","600")
#root.wm_grid(baseWidth="800", baseHeight="800")
#root.grid("800x800")
#_tkinter.TclError: wrong # args: should be "wm grid window ?baseWidth baseHeight
#widthInc heightInc?"
##self.title="Bingo Python"
###GUI voor BingPy code, altijd afsluiten met:
###bovenaan
root.mainloop()
'''
#Algemene Python Bingo klasse
class BingoPy
def
'''
#Labels voor alle nummers (50)
label1 = Label(root, text="1jghjgjkhjhg")
label1.grid()
label1.pack()
label2 = Label(root, text="2")
label2.grid()
label2.pack()
label3 = Label(root, text="3")
label3.grid()
label3.pack()
label4 = Label(root, text="4")
label4.grid()
label4.pack()
label5 = Label(root, text="5")
label5.grid()
label5.pack()
label6 = Label(root, text="6")
label6.grid()
label6.pack()
label7 = Label(root, text="7")
label7.grid()
label7.pack()
label8 = Label(root, text="8")
label8.grid()
label8.pack()
label9 = Label(root, text="9")
label9.grid()
label9.pack()
label10 = Label(root, text="10")
label10.grid()
label10.pack()
label11 = Label(root, text="11")
label11.grid()
label11.pack()
label12 = Label(root, text="12")
label12.grid()
label12.pack()
Label13 = Label(root, text="13")
Label13.grid()
Label13.pack()
label14 = Label(root, text="14")
label14.grid()
label14.pack()
label15 = Label(root, text="15")
label15.grid()
label15.pack()
label16 = Label(root, text="16")
label16.grid()
label16.pack()
label7 = Label(root, text="17")
label17.grid()
label17.pack()
label18 = Label(root, text="18")
label18.grid()
label18.pack()
label19 = Label(root, text="19")
label19.grid()
label19.pack()
label20 = Label(root, text="20")
label20.grid()
label20.pack()
label21 = Label(root, text="21")
label21.grid()
label21.pack()
label22 = Label(root, text='22')
label22.grid()
label22.pack()
label23 = Label(root, text="23")
label23.grid()
label23.pack()
label24 = Label(root, text="24")
label24.grid()
label24.pack()
label25 = Label(root, text="25")
label25.grid()
label25.pack()
label26 = Label(root, text="26")
label26.grid()
label26.pack()
label27 = Label(root, text="27")
label27.grid()
label27.pack()
label28.Label(root, text="28")
label28.grid()
label28.pack()
label29 = Label(root, text="29")
label29.grid()
label29.pack()
label30 = Label(root, text="30")
label30.grid()
label30.pack()
label31 = Label(root, text="31")
label31.grid()
label31.pack()
label32 = Label(root, text="32")
label32.grid()
label32.pack()
label33 = Label(root, text="33")
label33.grid()
label33.pack()
label34 = Label(root, text="34")
label34.grid()
label34.pack()
label35 = Label(root, text="35")
label35.grid()
label35.pack()
label36 = Label(root, text="36")
label36.grid()
label36.pack()
label37 = Label(root, text="37")
label37.grid()
label37.pack()
label38 = Label(root, text="38")
label38.grid()
label38.pack()
label39 = Label(root, text="39")
label39.grid()
label39.pack()
label40 = Label(root, text="40")
label40.grid()
label40.pack()
label41 = Label(root, text="41")
label41.grid()
label41.pack()
label42 = Label(root, text="42")
label42.grid()
label42.pack()
label43 = Label(root, text="43")
label43.grid()
label43.pack()
label44 = Label(root, text="44")
label44.grid()
label44.pack()
label45 = Label(root, text="45")
label45.grid()
label45.pack()
label46 = Label(root, text="46")
label46.grid()
label46.pack()
label47 = Label(root, text="47")
label47.grid()
label47.pack()
label48 = Label(root, text="48")
label48.grid()
label48.pack()
label49 = Label(root, text="49")
label49.grid()
label49.pack()
label50 = Label(root, text="50")
label50.grid()
label50.pack()
#Maakt het rood (en als het mogelijk is: doorstrepen) als het getrokken is
#Waarde-return in veld + niet meer zelfde nummer kunnen kiezen
#--------------------------------------------------------------------------
#Knoppen voor afsluiten en nieuw getal
##Afsluiten
#def bingoclose():
# print("Bingo Afsluiten")
'''
bAfsluiten = Button(root,text"Sluit Bingo Af")
bAfsluiten.pack()
'''
'''
{
'title' : ['BingPy'],
'summary' : ['Simple Bingo Python Application with rand.num generator'],
'authors' : ['Thomas']
#'date' : ['2015']
'base_url' : ['http://www.rainydays.eu']
}
'''
'''
Info en weblinks:
https://docs.python.org/3/library/random.html?highlight=random#module-random
http://infohost.nmt.edu/tcc/help/pubs/tkinter/tkinter.pdf (Python 2.7!)
https://wiki.scinet.utoronto.ca/wiki/images/4/41/Pwcgui.pdf
http://stackoverflow.com/questions/3643235/how-to-add-a-margin-to-a-tkinter
-window Margins in Python (padx, pady)
'''
You need to learn about data structures, like list.
You had root.mainloop() early on in the code. That starts a loop. Nothing after that is executed until the window is closed, which means it has to be at the end.
Choose one geometry manager. You can't use both grid() and pack() in the same parent widget, much less on the same child widget.
You had some typos, like label7 = instead of label17 =, and label28.Label instead of label28 = Label. Most of these would never have happened if you had used a list.
Obviously, 50 labels won't fit in a single column in a window of that size. You've got some decisions ahead of you involving window size, label placement, possible scrollbar, and so on.
The resulting code taking into account all these points (except the last) is shown below.
from tkinter import *
root = Tk()
root.wm_title("Bingo Python")
root.wm_maxsize("800","600")
root.wm_minsize("800","600")
labels = [Label(root, text=i) for i in range(1, 51)]
for label in labels:
label.pack()
root.mainloop()

Tkinter - setting string variables and getting entry values when looping

My goal is to be able to pass string variables to two different entries for user validation and return the user modified values. The code works fine if it is executed a single time; however, when looped, it only performs correctly during the first iteration of the loop. During subsequent iterations the string variables for the entries are blank.
I have experimented with update_idletasks() and time-sleep without luck. I am running Python 2.4 on Windows XP.
# -*- coding: cp1252 -*-
import Tkinter
def retrieve_text():
app_win.quit()
for item in range(3):
numero_dossier = item+1
version_dossier = item+2
app_win = Tkinter.Tk()
l = Tkinter.Label(app_win, text="Veuillez valider les informations suivantes et les corriger au besoin :")
l.grid(row=0, column=0, columnspan=2)
l.pack()
v1 = Tkinter.StringVar()
v1.set(numero_dossier)
l1 = Tkinter.Label(app_win, text="Numéro de dossier:", anchor='w', justify='left')
e1 = Tkinter.Entry(app_win, textvariable=v1)
l1.pack()
e1.pack()
v2 = Tkinter.StringVar()
v2.set(version_dossier)
l2 = Tkinter.Label(app_win, text="Version du dossier:", anchor='w', justify='left')
e2 = Tkinter.Entry(app_win, textvariable=v2)
l2.pack()
e2.pack()
app_button = Tkinter.Button(app_win,text="OK",command=retrieve_text)
app_button.pack()
app_win.mainloop()
app_win.withdraw()
numero_dossier = e1.get().strip()
version_dossier = e2.get().strip()
print numero_dossier, version_dossier
This is fundamentally broken:
for item in range(3):
...
app_win = Tkinter.Tk()
Tkinter is simply not designed to work this way. Your program should only ever create a single instance of the class Tk, and you should call mainloop exactly once.
There is no rationale in the question on why the widgets are being constructed multiple times, so I will take that as a mistake. Also, the name app_win for an Tkinter.Tk instance might be fooling you. Instantiating Tkinter.Tk starts a tcl interpreter, and then loads tk which as a "bonus" gives you a window.
The more sensible approach is creating the widgets only once, and then doing the multiple validations you are after. Here is your code adjusted for this:
import Tkinter
NUM_D = range(3)
VER_D = range(3)
CURR_D = 0
def retrieve_and_update_text():
global CURR_D
num_d = e1.get().strip()
ver_d = e2.get().strip()
print num_d, ver_d
CURR_D = (CURR_D + 1) % 3
v1.set(NUM_D[CURR_D] + 1)
v2.set(VER_D[CURR_D] + 2)
root = Tkinter.Tk()
l = Tkinter.Label(root, text=u"Label")
l.grid(row=0, column=0, columnspan=2)
v1 = Tkinter.StringVar()
l1 = Tkinter.Label(root, text=u"Num", anchor='w', justify='left')
e1 = Tkinter.Entry(root, textvariable=v1)
l1.grid(row=1)
e1.grid(row=1, column=1)
v2 = Tkinter.StringVar()
l2 = Tkinter.Label(root, text=u"Ver", anchor='w', justify='left')
e2 = Tkinter.Entry(root, textvariable=v2)
l2.grid(row=2)
e2.grid(row=2, column=1)
app_button = Tkinter.Button(root, text=u"OK", command=retrieve_and_update_text)
app_button.grid(row=3)
v1.set(NUM_D[CURR_D] + 1)
v2.set(VER_D[CURR_D] + 2)
root.mainloop()
Thanks to Bryan Oakley and mmgp, I was able to come up with the following code that does what I need, even though I am breaking the mainloop rule as it gets called during each iteration of the loop. All comments are welcome. Thanks again!
# -*- coding: cp1252 -*-
import Tkinter
root = Tkinter.Tk()
def retrieve_and_update_text():
#global CURR_D
dossier = e1.get().strip()
version = e2.get().strip().upper()
print dossier, version
root.quit()
for item in range(3):
dossier = item+1
version = item+2
l = Tkinter.Label(root, text=u"Veuillez valider les informations suivantes et les corriger au besoin :")
l.grid(row=0, column=0, columnspan=2)
v1 = Tkinter.StringVar()
l1 = Tkinter.Label(root, text=u"Dossier :", anchor='w', justify='left')
e1 = Tkinter.Entry(root, textvariable=v1)
l1.grid(row=1)
e1.grid(row=1, column=1)
v2 = Tkinter.StringVar()
l2 = Tkinter.Label(root, text=u"Version :", anchor='w', justify='left')
e2 = Tkinter.Entry(root, textvariable=v2)
l2.grid(row=2)
e2.grid(row=2, column=1)
app_button = Tkinter.Button(root, text=u"OK", command=retrieve_and_update_text)
app_button.grid(row=3)
v1.set(dossier)
v2.set(version)
root.mainloop()
if item == range(3)[-1]: # if last item
root.withdraw()

Categories