In this code, hitting the weightpos/weightneg buttons should change the value by 5. When using the original buttons that arent created from the addrow() function, it works fine, but using the created buttons it only increments by 1.
Code:
import tkinter as tk
from tkinter import ttk
from tkinter import *
from PIL import ImageTk, Image
import os
weight_entry='0'
root=tk.Tk()
movement_chest = ["Flat Bench", 'Incline Bench', 'Decline Bench', 'Flat DB Press', "Incline DB Press", 'High-Low Cable Raise', "Low-High Cable Raise",]
files_movement_chest = ["flat_bench.gif", 'incline_bench.gif', 'decline_bench.gif', 'db_flat.gif', "db_incline.gif", 'high_low_cable.gif', "low_high_cable.gif",]
row_counter=1
class Toolbar(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Workout Tracker")
menubar = Menu(self.master)
self.master.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Exit", command=self.onExit)
menubar.add_cascade(label="File", menu=fileMenu)
def onExit(self):
self.quit()
# Create a variable to hold the image reference
image_label = None
img = None
# Set button function
def plusminus(increment, entry, row_counter):
if entry.get() == '':
new_value = 0
else:
current_value = int(entry.get()) # Get the current value from the entry widget
if entry == weight_entry:
# If the entry widget is the weight field, change the value by 5
if increment:
new_value = current_value + 5
else:
new_value = current_value - 5
else:
# For other fields like sets, change by 1
if increment:
new_value = current_value + 1
print(entry)
else:
new_value = current_value - 1
if new_value < 0:
new_value = 0
entry.delete(0, tk.END) # Clear the entry
entry.insert(0, str(new_value)) # Insert the new value
def on_combobox_select(event=None, row_counter=0): # Allow for manual function call (no event)
global image_label, img # Use global variables
motion = Dropdown.get()
# Remove the old image if it exists
if image_label:
image_label.destroy()
# Find the index of the selected motion in movement_chest
if motion in movement_chest:
index = movement_chest.index(motion) # Get the index of the selected motion
# Get the corresponding filename for the selected motion
img_path = files_movement_chest[index]
# Check if the image file exists and load it
if os.path.exists(img_path):
img = ImageTk.PhotoImage(Image.open(img_path))
else:
print(f"Image file '{img_path}' not found.")
img = None
# Only add the label if the image is loaded correctly
if img:
image_label = Label(root, image=img)
image_label.grid(row=row_counter, column=0, columnspan=3, sticky="nsew") # Use grid here with spanning
else:
img_path = "workout.gif"
if os.path.exists(img_path):
img = ImageTk.PhotoImage(Image.open(img_path))
else:
print("Image file 'workout.gif' not found.")
img = None
if img: # Only add the label if the image is loaded correctly
panel = Label(root, image=img)
panel.grid(row=row_counter, column=0, columnspan=3, sticky="nsew") # Use grid here with spanning
# Create a function that adds a new row of widgets
def add_row():
global row_counter
# Add row-specific widgets like motion dropdown, weight entry, set entry, etc.
label_dropdown = tk.Label(root, text='Motion')
label_dropdown.grid(row=row_counter, column=4, pady=(15, 0), sticky='n')
# Create a new row of widgets for motion
motion_dropdown = ttk.Combobox(
root,
values=movement_chest,
state="readonly",
)
motion_dropdown.grid(row=row_counter, column=4, padx=5, pady=5)
motion_dropdown.bind("<<ComboboxSelected>>", lambda event: on_combobox_select(event, row_counter))
# Create weight entry for this row
label_weight = tk.Label(root, text='Weight')
label_weight.grid(row=row_counter, column=5, pady=(15, 0), sticky='n')
weight_entry = ttk.Entry(root)
weight_entry.grid(row=row_counter, column=5, padx=5, pady=5)
# Buttons for incrementing/decrementing weight
btn_weightpos = tk.Button(root, text='+', command=lambda: plusminus(True, weight_entry, row_counter))
btn_weightpos.grid(row=row_counter, column=5, padx=(0, 19), pady=(0, 8), sticky='s')
btn_weightneg = tk.Button(root, text='-', command=lambda: plusminus(False, weight_entry, row_counter))
btn_weightneg.grid(row=row_counter, column=5, padx=(19, 0), pady=(0, 8), sticky='s')
# Create set entry for this row
label_set = tk.Label(root, text='Sets')
label_set.grid(row=row_counter, column=6, pady=(15, 58), sticky='n')
set_entry = ttk.Entry(root)
set_entry.grid(row=row_counter, column=6, padx=5, pady=5)
# Buttons for incrementing/decrementing sets
btn_setpos = tk.Button(root, text='+', command=lambda: plusminus(True, set_entry, row_counter))
btn_setpos.grid(row=row_counter, column=6, padx=(0, 19), pady=(0, 8), sticky='s')
btn_setneg = tk.Button(root, text='-', command=lambda: plusminus(False, set_entry, row_counter))
btn_setneg.grid(row=row_counter, column=6, padx=(19, 0), pady=(0, 8), sticky='s')
# Create an image label placeholder for each row (so that we can update it later)
image_label = None
img = None
# Increment row_counter for the next row
row_counter += 1
# Dropdown (Combobox)
Dropdown = ttk.Combobox(
root,
values=movement_chest,
state="readonly",
)
label_dropdown = tk.Label(root, text='Motion')
label_dropdown.grid(row=0, column=4, pady=(70, 0), sticky='n')
Dropdown.grid(row=0, column=4, padx=5, pady=5)
Dropdown.bind("<<ComboboxSelected>>", on_combobox_select)
# Weight field
label_weight = tk.Label(root, text='Weight')
weight_entry = ttk.Entry(root, text='Weight')
label_weight.grid(row=0, column=5, pady=(70, 0), sticky='n')
weight_entry.grid(row=0, column=5, padx=5, pady=5)
# button to increment the weight value
btn_weightpos = tk.Button(root, text='+', command=lambda: plusminus(True, weight_entry, 0)) # Using lambda to pass argument
btn_weightpos.grid(row=0, column=5, padx=(0, 19), pady=(0, 65), sticky='s')
# button to decrement the weight value
btn_weightneg = tk.Button(root, text='-', command=lambda: plusminus(False, weight_entry, 0))
btn_weightneg.grid(row=0, column=5, padx=(19, 0), pady=(0, 65), sticky='s')
# Set field
label_set = tk.Label(root, text='Sets')
set_entry = ttk.Entry(root, text='Sets')
label_set.grid(row=0, column=6, pady=(70, 0), sticky='n')
set_entry.grid(row=0, column=6, padx=5, pady=5)
# button to increment the set value
btn_setpos = tk.Button(root, text='+', command=lambda: plusminus(True, set_entry, 0)) # Using lambda to pass argument
btn_setpos.grid(row=0, column=6, padx=(0, 19), pady=(0, 65), sticky='s')
# button to decrement the set value
btn_setneg = tk.Button(root, text='-', command=lambda: plusminus(False, set_entry, 0))
btn_setneg.grid(row=0, column=6, padx=(19, 0), pady=(0, 65), sticky='s')
# Manually trigger the combobox selection to load the default image (workout.gif)
on_combobox_select()
# Add "Add Row" button
add_row_button = tk.Button(root, text="Add Row", command=add_row)
add_row_button.grid(row=0, column=7, padx=5, pady=5)
# Initial row setup (first row)
root.mainloop()
I tried using variables instead of weight_entry when calling the function and it did not work
In this code, hitting the weightpos/weightneg buttons should change the value by 5. When using the original buttons that arent created from the addrow() function, it works fine, but using the created buttons it only increments by 1.
Code:
import tkinter as tk
from tkinter import ttk
from tkinter import *
from PIL import ImageTk, Image
import os
weight_entry='0'
root=tk.Tk()
movement_chest = ["Flat Bench", 'Incline Bench', 'Decline Bench', 'Flat DB Press', "Incline DB Press", 'High-Low Cable Raise', "Low-High Cable Raise",]
files_movement_chest = ["flat_bench.gif", 'incline_bench.gif', 'decline_bench.gif', 'db_flat.gif', "db_incline.gif", 'high_low_cable.gif', "low_high_cable.gif",]
row_counter=1
class Toolbar(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Workout Tracker")
menubar = Menu(self.master)
self.master.config(menu=menubar)
fileMenu = Menu(menubar)
fileMenu.add_command(label="Exit", command=self.onExit)
menubar.add_cascade(label="File", menu=fileMenu)
def onExit(self):
self.quit()
# Create a variable to hold the image reference
image_label = None
img = None
# Set button function
def plusminus(increment, entry, row_counter):
if entry.get() == '':
new_value = 0
else:
current_value = int(entry.get()) # Get the current value from the entry widget
if entry == weight_entry:
# If the entry widget is the weight field, change the value by 5
if increment:
new_value = current_value + 5
else:
new_value = current_value - 5
else:
# For other fields like sets, change by 1
if increment:
new_value = current_value + 1
print(entry)
else:
new_value = current_value - 1
if new_value < 0:
new_value = 0
entry.delete(0, tk.END) # Clear the entry
entry.insert(0, str(new_value)) # Insert the new value
def on_combobox_select(event=None, row_counter=0): # Allow for manual function call (no event)
global image_label, img # Use global variables
motion = Dropdown.get()
# Remove the old image if it exists
if image_label:
image_label.destroy()
# Find the index of the selected motion in movement_chest
if motion in movement_chest:
index = movement_chest.index(motion) # Get the index of the selected motion
# Get the corresponding filename for the selected motion
img_path = files_movement_chest[index]
# Check if the image file exists and load it
if os.path.exists(img_path):
img = ImageTk.PhotoImage(Image.open(img_path))
else:
print(f"Image file '{img_path}' not found.")
img = None
# Only add the label if the image is loaded correctly
if img:
image_label = Label(root, image=img)
image_label.grid(row=row_counter, column=0, columnspan=3, sticky="nsew") # Use grid here with spanning
else:
img_path = "workout.gif"
if os.path.exists(img_path):
img = ImageTk.PhotoImage(Image.open(img_path))
else:
print("Image file 'workout.gif' not found.")
img = None
if img: # Only add the label if the image is loaded correctly
panel = Label(root, image=img)
panel.grid(row=row_counter, column=0, columnspan=3, sticky="nsew") # Use grid here with spanning
# Create a function that adds a new row of widgets
def add_row():
global row_counter
# Add row-specific widgets like motion dropdown, weight entry, set entry, etc.
label_dropdown = tk.Label(root, text='Motion')
label_dropdown.grid(row=row_counter, column=4, pady=(15, 0), sticky='n')
# Create a new row of widgets for motion
motion_dropdown = ttk.Combobox(
root,
values=movement_chest,
state="readonly",
)
motion_dropdown.grid(row=row_counter, column=4, padx=5, pady=5)
motion_dropdown.bind("<<ComboboxSelected>>", lambda event: on_combobox_select(event, row_counter))
# Create weight entry for this row
label_weight = tk.Label(root, text='Weight')
label_weight.grid(row=row_counter, column=5, pady=(15, 0), sticky='n')
weight_entry = ttk.Entry(root)
weight_entry.grid(row=row_counter, column=5, padx=5, pady=5)
# Buttons for incrementing/decrementing weight
btn_weightpos = tk.Button(root, text='+', command=lambda: plusminus(True, weight_entry, row_counter))
btn_weightpos.grid(row=row_counter, column=5, padx=(0, 19), pady=(0, 8), sticky='s')
btn_weightneg = tk.Button(root, text='-', command=lambda: plusminus(False, weight_entry, row_counter))
btn_weightneg.grid(row=row_counter, column=5, padx=(19, 0), pady=(0, 8), sticky='s')
# Create set entry for this row
label_set = tk.Label(root, text='Sets')
label_set.grid(row=row_counter, column=6, pady=(15, 58), sticky='n')
set_entry = ttk.Entry(root)
set_entry.grid(row=row_counter, column=6, padx=5, pady=5)
# Buttons for incrementing/decrementing sets
btn_setpos = tk.Button(root, text='+', command=lambda: plusminus(True, set_entry, row_counter))
btn_setpos.grid(row=row_counter, column=6, padx=(0, 19), pady=(0, 8), sticky='s')
btn_setneg = tk.Button(root, text='-', command=lambda: plusminus(False, set_entry, row_counter))
btn_setneg.grid(row=row_counter, column=6, padx=(19, 0), pady=(0, 8), sticky='s')
# Create an image label placeholder for each row (so that we can update it later)
image_label = None
img = None
# Increment row_counter for the next row
row_counter += 1
# Dropdown (Combobox)
Dropdown = ttk.Combobox(
root,
values=movement_chest,
state="readonly",
)
label_dropdown = tk.Label(root, text='Motion')
label_dropdown.grid(row=0, column=4, pady=(70, 0), sticky='n')
Dropdown.grid(row=0, column=4, padx=5, pady=5)
Dropdown.bind("<<ComboboxSelected>>", on_combobox_select)
# Weight field
label_weight = tk.Label(root, text='Weight')
weight_entry = ttk.Entry(root, text='Weight')
label_weight.grid(row=0, column=5, pady=(70, 0), sticky='n')
weight_entry.grid(row=0, column=5, padx=5, pady=5)
# button to increment the weight value
btn_weightpos = tk.Button(root, text='+', command=lambda: plusminus(True, weight_entry, 0)) # Using lambda to pass argument
btn_weightpos.grid(row=0, column=5, padx=(0, 19), pady=(0, 65), sticky='s')
# button to decrement the weight value
btn_weightneg = tk.Button(root, text='-', command=lambda: plusminus(False, weight_entry, 0))
btn_weightneg.grid(row=0, column=5, padx=(19, 0), pady=(0, 65), sticky='s')
# Set field
label_set = tk.Label(root, text='Sets')
set_entry = ttk.Entry(root, text='Sets')
label_set.grid(row=0, column=6, pady=(70, 0), sticky='n')
set_entry.grid(row=0, column=6, padx=5, pady=5)
# button to increment the set value
btn_setpos = tk.Button(root, text='+', command=lambda: plusminus(True, set_entry, 0)) # Using lambda to pass argument
btn_setpos.grid(row=0, column=6, padx=(0, 19), pady=(0, 65), sticky='s')
# button to decrement the set value
btn_setneg = tk.Button(root, text='-', command=lambda: plusminus(False, set_entry, 0))
btn_setneg.grid(row=0, column=6, padx=(19, 0), pady=(0, 65), sticky='s')
# Manually trigger the combobox selection to load the default image (workout.gif)
on_combobox_select()
# Add "Add Row" button
add_row_button = tk.Button(root, text="Add Row", command=add_row)
add_row_button.grid(row=0, column=7, padx=5, pady=5)
# Initial row setup (first row)
root.mainloop()
I tried using variables instead of weight_entry when calling the function and it did not work
Share Improve this question asked 2 days ago Benjamin WalkerBenjamin Walker 1 New contributor Benjamin Walker is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 1- Please edit your question down to a minimal reproducible example, that is, only the code necessary to reproduce the issue. – JRiggles Commented 2 days ago
2 Answers
Reset to default 0You'll need to update your lambda
s in add_row
to correctly pass in the local weight_entry
widget:
btn_weightpos = tk.Button(root, text='+', command=lambda entry=weight_entry: plusminus(True, entry, row_counter))
btn_weightpos.grid(row=row_counter, column=5, padx=(0, 19), pady=(0, 8), sticky='s')
btn_weightneg = tk.Button(root, text='-', command=lambda entry=weight_entry: plusminus(False, entry, row_counter))
btn_weightneg.grid(row=row_counter, column=5, padx=(19, 0), pady=(0, 8), sticky='s')
The weight_entry
created inside add_row()
is not the same as the global created weight_entry
, so the checking entry == weight_entry
inside plusminus()
will be evaluated as False
because weight_entry
inside plusminus()
refers to the global one.
You can create a custom class for the weight entry:
class WeightEntry(ttk.Entry): pass
Then create those weight entry using this custom class:
def add_row():
...
# local one
weight_entry = WeightEntry(...)
...
...
# global one
weight_entry = WeightEntry(...)
...
Then you can use isinstance(entry, WeightEntry)
inside plusminus()
to check whether entry
is an instance of WeightEntry
:
def plusminus(increment, entry, row_counter):
if entry.get() == '':
new_value = 0
else:
...
if isinstance(entry, WeightEntry):
...
...
Another suggestion is to pass the actual value (+5/-5, +1/-1) to the argument increment
of plusminus()
and add this actual value to the passed entry
, i.e. new_value = max(current_value+increment, 0)
.