Related
Good,
I'm trying to sum the values of a column, while inputting it. Since I put a code in the entry and check if it exists and put it in columns in treeview, and I would like to add only the "price" values, but I can't do it, I get the data from the price column, but I can't get if This 5.99 I have entered another 5.99 add up and give me a total, as I add a price.
What I can be doing wrong? or what I have wrong
Any additional information would be appreciated.
def Cesta(self):
self.conex()
self.b_codigo = self.s_Codigo.get()
self.sql3 = "SELECT * FROM productos WHERE codigo = %s"
self.mycursor.execute(self.sql3,[(self.b_codigo)])
self.r_codigo = self.mycursor.fetchall()
self.row3 = [item['nombre'] for item in self.r_codigo]
if self.s_Codigo.get() == "":
MessageBox.showinfo("ERROR", "DEBES INTRODUCIR DATOS", icon="error")
elif self.r_codigo:
for self.x2 in self.r_codigo:
print (self.x2["nombre"], self.x2["talla"], self.x2["precio"]+"€")
self.tree.insert('', 'end', text=self.x2["nombre"], values=(self.x2["talla"],self.x2["precio"]+" €"))
print(self.x2["fecha"])
for self.item in self.tree.get_children():
self.resultado = 0
self.celda = int(self.tree.set(self.item,"col2"))
self.total = int(self.resultado) + int(float(self.celda))
print(self.total)
else:
MessageBox.showinfo("ERROR", "EL CODIGO INTRODUCIDO NO ES CORRECTO", icon="error")
self.clear_entry()
`
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
return self.func(*args)
File "/Users/tomas/Downloads/PROYECTO/main.py", line 205, in Cesta
self.celda = int(self.tree.set(self.item,"col2"))
ValueError: invalid literal for int() with base 10: '134,99 €'
[Finished in 6.7s]
`
self.tree = ttk.Treeview(self.pagina1,columns=("col1","col2"), height=50)
self.tree.grid(column=0, row=2, padx=50, pady=100)
### COLUMNAS ###
self.tree.column("#0",width=250)
self.tree.column("col1",width=150, anchor=CENTER)
self.tree.column("col2",width=150, anchor=CENTER)
### NOMBRES COLUMNAS ###
self.tree.heading("#0", text="Articulo", anchor=CENTER)
self.tree.heading("col1", text="Talla", anchor=CENTER)
self.tree.heading("col2", text="Precio", anchor=CENTER)
Everything else is going well for me, but the part in which I want to add the results of the price column does not
What am I doing wrong, to be able to add the values of the prices column every time I insert a new product?
I have already managed to solve the error, the new price is already added to the old one, thanks for making me reflect on it.
for self.x2 in self.r_codigo:
print (self.x2["nombre"], self.x2["talla"], self.x2["precio"]+"€")
self.tree.insert('', 'end', text=self.x2["nombre"], values=(self.x2["talla"],self.x2["precio"]))
self.total = 0
for self.item in self.tree.get_children():
self.celda = float(self.tree.set(self.item,"col2"))
self.total+=self.celda
print(self.total)
I apologise for the long code and confusing inputs, I had to do some stuff in retrospect. This program counts (types the number) to a certain number (capped at 100 because I got lazy) and it designed for a game (hence the / and space, enter inputs). Everything works well, you can try it out in notepad.
However, when running the program everything freezes until the counting is complete. I've heard about threading although I'm not able to understand it, unfortunately. What I want to achieve is that the program can run and the user can still interact with it while it is running and pause/stop the program if they so desire. I've setup a naive STOP button but that doesn't work when its running and also closes the program which is unideal, as I'd rather just pause or cancel counting.
from pynput import keyboard as keyboard3
import time
import keyboard as keyboard2
import tkinter as tk
from functools import partial
import sys
num2words = {1: 'One', 2: 'Two', 3: 'Three', 4: 'Four', 5: 'Five',
6: 'Six', 7: 'Seven', 8: 'Eight', 9: 'Nine', 10: 'Ten',
11: 'Eleven', 12: 'Twelve', 13: 'Thirteen', 14: 'Fourteen',
15: 'Fifteen', 16: 'Sixteen', 17: 'Seventeen', 18: 'Eighteen', 19: 'Nineteen'}
num2wordsTens = ['Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety']
def exitProgram():
sys.exit()
def num2text(numb,caps):
"""
:param numb: number to convert to text
:param caps: True/False capital returns
:return: Take the integer and returns text equivalance
"""
if 0 <= numb <= 19:
if caps:
return (num2words[numb]).upper()
else:
return (num2words[numb])
elif 20 <= numb <= 99:
tens, remainder = divmod(numb, 10)
if caps:
return (num2wordsTens[tens - 2] + ' ' + num2words[remainder] if remainder else num2wordsTens[tens - 2]).upper()
#Can add "+ '-' +" if we want a hyphonate it.
else:
return num2wordsTens[tens - 2] + ' ' + num2words[remainder] if remainder else num2wordsTens[tens - 2]
elif numb == 100:
return "One Hundred"
else:
print('Number out of implemented range of numbers.')
keyboard = keyboard3.Controller()
def jumpingJacks(maxNumb, initDelay, intervalDelay, caps, grammar):
"""
:param maxNumb: Max number for the list of numbers
:param initDelay: Initial delay before starting
:param intervalDelay: Delay between sending messages
:param grammar: If true, add fullstop.
:return: none
"""
time.sleep(initDelay.get())
numberInterval = list(range(1, maxNumb.get()+1))
for integer in numberInterval:
keyboard.tap('/')
time.sleep(0.1)
if grammar:
keyboard.type(num2text(numberInterval[integer-1], caps)+'.')
else:
keyboard.type(num2text(numberInterval[integer-1], caps))
time.sleep(0.1)
keyboard2.press('enter')
time.sleep(0.1)
keyboard2.press('space')
time.sleep(0.5)
keyboard2.release('space')
time.sleep(intervalDelay.get())
window = tk.Tk()
window.geometry("500x200")
numJJ = tk.IntVar(value=10)
intDelay = tk.IntVar(value=5)
JJDelay = tk.IntVar(value=1.5)
capsCheck = tk.BooleanVar()
grammarCheck = tk.BooleanVar()
frame_top = tk.Frame(master=window)
frame_1 = tk.Frame(master=frame_top)
labelt1 = tk.Label(master=frame_1, text="Number of JJ")
entryt1 = tk.Entry(master=frame_1, width=5, textvariable=numJJ)
labelt1.pack(side=tk.TOP, padx=10,pady=(5,1))
entryt1.pack(side=tk.TOP)
frame_2 = tk.Frame(master=frame_top)
labelt2 = tk.Label(master=frame_2, text="Initial Delay (s)")
entryt2 = tk.Entry(master=frame_2, width=3, textvariable=intDelay)
labelt2.pack(side=tk.TOP,padx=10, pady=(5,1))
entryt2.pack()
frame_3 = tk.Frame(master=frame_top)
labelt3 = tk.Label(master=frame_3, text="JJ Delay (s)")
entryt3 = tk.Entry(master=frame_3, width=3, textvariable=JJDelay)
labelt3.pack(side=tk.TOP,padx=10, pady=(5,1))
entryt3.pack()
frame_4 = tk.Frame(master=frame_top)
labelt4 = tk.Label(master=frame_4, text="Capslock?")
checkt4 = tk.Checkbutton(master=frame_4, onvalue=True, offvalue=False, variable=capsCheck)
labelt4.pack(side=tk.TOP,padx=10,pady=(5,1))
checkt4.pack()
frame_5 = tk.Frame(master=frame_top)
labelt5 = tk.Label(master=frame_5, text="Grammar?")
checkt5 = tk.Checkbutton(master=frame_5, onvalue=True, offvalue=False, variable=grammarCheck)
labelt5.pack(side=tk.TOP,padx=10, pady=(5,1))
checkt5.pack()
frame_bottom = tk.Frame(master=window)
jumpingJacks = partial(jumpingJacks, numJJ, intDelay, JJDelay, capsCheck, grammarCheck)
toggleButton = tk.Button(master=frame_bottom, text="Begin", command=jumpingJacks)
toggleButton.pack()
ExitButton = tk.Button(master=frame_bottom,text="Stop",command=exitProgram)
ExitButton.pack()
frame_1.pack(side=tk.LEFT)
frame_2.pack(side=tk.LEFT)
frame_3.pack(side=tk.LEFT)
frame_4.pack(side=tk.LEFT)
frame_5.pack(side=tk.LEFT)
frame_top.pack()
frame_bottom.pack()
window.mainloop()
I creating GUI interacting with treeview and I want to get all the value inside the list and show it in treeview window. I have a add button and once I click it, it will work fine. But on the second time, it shows an error Item 1 already exists. It also does not added to the list.
This is my code:
from tkinter import *
from tkinter import ttk
root = Tk()
def add1():
global count
for i in tree_table.get_children():
tree_table.delete(i)
get_name = txt_name.get()
get_ref = txt_ref.get()
get_age = txt_age.get()
get_email = txt_email.get()
data_list.append((get_name, get_ref, get_age, get_email))
for item in data_list:
tree_table.insert(parent='', index='end', iid=count, text=f'{count + 1}', values=(item))
txt_name.delete(0, END)
txt_ref.delete(0, END)
txt_age.delete(0, END)
txt_email.delete(0, END)
count += 1
print(data_list)
tree_table = ttk.Treeview(root)
global count
count = 0
data_list = []
tree_table['columns'] = ("Name", "Reference No.", "Age", "Email Address")
tree_table.column("#0", width=30)
tree_table.column("Name", width=120, anchor=W)
tree_table.column("Reference No.", width=120, anchor=W)
tree_table.column("Age", width=120, anchor=W)
tree_table.column("Email Address", width=120, anchor=W)
headings = ["#0", "Name", "Reference No.", "Age", "Email Address"]
txt_headings = ["No.", "Name", "Reference No.", "Age", "Email Address"]
for i in range(len(headings)):
tree_table.heading(headings[i], text=txt_headings[i], anchor=W)
txt_name = Entry(root, width=20)
txt_name.pack()
txt_ref = Entry(root, width=20)
txt_ref.pack()
txt_age = Entry(root, width=20)
txt_age.pack()
txt_email = Entry(root, width=20)
txt_email.pack()
btn_enter = Button(root, text="Add", width=20, command=add1)
btn_enter.pack()
tree_table.pack()
root.mainloop()
Traceback:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python\Python385\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "d:/Code/Cpet5/new.py", line 32, in add1
tree_table.insert(parent='', index='end', iid=count, text=f'{count + 1}', values=(item))
File "C:\Python\Python385\lib\tkinter\ttk.py", line 1366, in insert
res = self.tk.call(self._w, "insert", parent, index,
_tkinter.TclError: Item 1 already exists
How do I refresh the treeview to reflect the changes made in the list?
Quick fix:
Get rid of the iid argument:
tree_table.insert(parent='', index='end', text=f'{count + 1}', values=(item))
But that will create an issue of the No. column getting same value always.
Actual fix:
So the actual problem is your list contains alot of values, you should get rid of those values once you insert it, so the code should be something like:
def add1():
global count
get_name = txt_name.get()
get_ref = txt_ref.get()
get_age = txt_age.get()
get_email = txt_email.get()
data_list.clear() #clear the list
data_list.append((get_name, get_ref, get_age, get_email)) #append to the empty list
for item in data_list:
tree_table.insert(parent='', index='end',iid=count, text=f'{count + 1}', values=(item))
txt_name.delete(0, END)
txt_ref.delete(0, END)
txt_age.delete(0, END)
txt_email.delete(0, END)
count += 1
print(data_list)
This way your clearing whats inside of the list each time and appending new values to list.
With your older code you can see that first time the the list is [('1', '1', '1', '1')] and when the next set of values is appended it becomes [('1', '1', '1', '1'), ('2', '2', '2', '2')] so there is not enough space accommodate all this value in? Anyway this fixes it. Or you could also make a tuple of those inputs and then pass that tuple as the values for treeview without looping, like acw1668 did.
You don't need to clear the treeview before adding new row to it:
def add1():
global count
get_name = txt_name.get()
get_ref = txt_ref.get()
get_age = txt_age.get()
get_email = txt_email.get()
row = (get_name, get_ref, get_age, get_email)
data_list.append(row)
count += 1
tree_table.insert(parent='', index='end', iid=count, text=f'{count}', values=row)
txt_name.delete(0, END)
txt_ref.delete(0, END)
txt_age.delete(0, END)
txt_email.delete(0, END)
print(data_list)
I am writing a calendar program using the tkinter module and clicking on each day on the grid will print out the current day's date (month/day/year). However, I also want to add another section at the bottom that will show what day of the year it is. Like this:
For example, January 1, 2020 would be the first day of the year, March 20 will be the 80th day of the year, etc. I want my radio buttons to be able to control both of these variables, the date as a string, and the day of the year as an integer. Is this possible?
strDate = StringVar()
labelDate = Label(frameDay, textvariable=strDate, width=28,
font=("Consolas", "15", "bold")).grid(row=1, column=1)
# Creating the calendar grid
while day <= self.returnMaxDay():
currentDay = Date(self.month, day, self.year)
radDay = Radiobutton(frameCalendar, text=str(day),
font=("Consolas", "15", "bold"), indicatoron=0, width=4, height=1,
variable=strDate, value=str(currentDay.returnDayName()) + ", "
+ str(currentDay.returnMonthName()) + " "
+ str(day) + ", " + str(currentDay.year))
radDay.grid(row=row, column=weekDay)
day += 1
weekDay += 1
if weekDay == 7:
row += 1
weekDay = 0
labelDayOfYear = Label(window, text=str(self.dayOfYear()), font=("Consolas", "20")).pack()
It is simple example which uses command= in Radiobutton to run function which changes text it three Labels.
Normally command= expect function's name without () and arguments so I use lambda to assing function with arguments.
command=lambda d=current_day:on_click(d))
I also use d=current_day to create new variable d for every function. Without d=current_day all functions would use reference to the same variable current_day and all functions would use the same (last) value in current_day.
import tkinter as tk
import datetime
# --- functions ---
def on_click(value):
print(value)
label_date['text'] = value.strftime('%a, %b %d, %Y')
label_day['text'] = value.strftime('Day: %d')
label_weekday['text'] = value.strftime('Weekday: %a')
# --- main ---
root = tk.Tk()
radiobutton_var = tk.StringVar()
year = 2020
month = 4
row = 0
for day in range(1, 32):
try:
current_day = datetime.datetime(year, month, day)
date_str = current_day.strftime('%a, %m %d, %Y')
weekday = current_day.weekday()
radiobutton_day = tk.Radiobutton(root,
text=str(day),
indicatoron=0,
variable=radiobutton_var,
value=date_str,
#value=day,
command=lambda x=current_day:on_click(x))
radiobutton_day.grid(row=row, column=weekday, sticky='we')
if weekday == 6:
row += 1
radiobutton_day['bg'] = '#faa'
except ValueError as ex:
print(ex)
break
label_date = tk.Label(root, text='?')
label_date.grid(row=10, columnspan=10)
label_day = tk.Label(root, text='Day: ?')
label_day.grid(row=11, columnspan=10)
label_weekday = tk.Label(root, text='Weekday: ?')
label_weekday.grid(row=12, columnspan=10)
root.mainloop()
BTW: I use datetime to generate dates and try/except to catch error when date is incorrect.
I also use strftime to format date - see more on page strftime.org
I want to sum values from treeview column no matter if one of the rows is empty, also I want to delete that row when the Sum button is pressed. I wrote a code but I always get this error:
IndexError: string index out of range
This is the code:
from tkinter import*
from tkinter import ttk
myApp = Tk()
myApp.title(" Program ")
TotalEntry=Entry(myApp, width=18)
TotalEntry.grid(row=0,column=1, sticky="e", pady=5)
NewTree= ttk.Treeview(myApp, height=7)
NewTree['show'] = 'headings'
NewTree["columns"]=("1")
NewTree.column("1", width=80, anchor="center")
NewTree.heading("1", text="ID")
item = NewTree.insert("", "end", values=(2))
item = NewTree.insert("", "end", values=(""))
item = NewTree.insert("", "end", values=(6))
NewTree.grid(row=0,column=0)
def SumAllCosts():
for i in NewTree.get_children():
a = NewTree.item(i,"values")[0]
if len(a)==0:
NewTree.delete(i)
SumPreCosts=0.0
for child in NewTree.get_children():
PreCost=round(float(NewTree.item(child,"values")[0]),2)
SumPreCosts += PreCost
TotalEntry.delete(0,"end")
TotalEntry.insert(0,round(SumPreCosts,2))
Sum=Button(myApp,text=" Sum ",command=SumAllCosts)
Sum.grid(row=0,column=2, sticky="w",pady=5)
myApp.mainloop()
If you print type(NewTree.item(i, "values")) and repr(NewTree.item(i, "values")), you can see that this returns
<class 'tuple'> ('2',)
<class 'str'> ''
<class 'tuple'> ('6',)
As you can see, for the 2 and 6 entry, this returns a tuple so you can do NewTree.item(i, "values")[0] to get the first value. However, the empty item is returned as an empty string, so NewTree.item(i, "values")[0] gives the error you describe.
You can change that part of the code to check if NewTree.item(i, "values") is not empty:
for i in NewTree.get_children():
if not NewTree.item(i, "values"):
NewTree.delete(i)