In the given code if I select the material in the 6th row or the last row then it is showing in that respective row.
If I add any row afer that and select the material, then also it is showing the material in that last row for example it would be 7th row here.
However, if I select the material in 2nd row firstly, then it is showing the material in the 2nd row.
Now comes the devil, if I add a row after 2nd row and a new row has been added at 3rd position. If I select the material in this layer then the material selected or properties related to that will be showed in the nect row which is 4th.
I have attached the screenshots also.
Here is my code
from tkinter import *from tkinter import ttkfrom tkinter.ttk import *import pandas as pdfrom functools import partialdef open_layers_window(root): layers_window = Toplevel(root) layers_window.title("Substrate Data") layers_window.geometry('1800x400') layers_window.resizable(True, True) # Specify the path to your Excel file excel_file_path = 'Substances Database.xlsx' # Load the Excel file excel_data = pd.ExcelFile(excel_file_path) # Get the names of all sheets in the Excel file sheet_names = excel_data.sheet_names # Choose the active sheet (you mentioned one sheet is active) active_sheet_name = excel_data.sheet_names[1] # Change this based on your actual sheet name # Read the data from the active sheet df = pd.read_excel(excel_data, sheet_name=active_sheet_name, index_col=0) # Extract material names from the 'substrate' sheet material_names = df.columns[2:].tolist() # Assuming material names start from column 2 # Specify the column names column_names = ['Layer\nNo.', 'Layer\nname', 'Material', 'Description', 'Grammage\n[g/m\u00b2]', 'Thickness\n[µm]','Density\n[kg/m\u00b3]', 'Specific heat capacity\n[kJ/kg.K]', 'Heat conductivity\n[W/m.K]','Starting Temperature\n[°C]'] global density_entries global specific_heat_capacity_entries global heat_conductivity_entries global description_entries global grammage_entries global thickness_entries density_entries = [] specific_heat_capacity_entries = [] heat_conductivity_entries = [] description_entries = [] grammage_entries = [] thickness_entries = [] i = 5 rows = [] def setup_ui(root): def calculate_grammage(row_num, density_value): try: density_entry = density_entries[row_num] thickness_entry = thickness_entries[row_num] grammage_entry = grammage_entries[row_num] # Get the values from the entry fields density_str = density_entry.get().strip() thickness_str = thickness_entry.get().strip() grammage_str = grammage_entry.get().strip() # Check if density is not modified if density_str: density=float(density_str) #if thickness_str and not grammage_str: # Calculate grammage if only thickness is given #thickness = float(thickness_str) #grammage = density * thickness / 1000 #grammage_entry.delete(0, END) #grammage_entry.insert(0, f'{grammage:.2f}') #elif grammage_str and not thickness_str: # Calculate thickness if only grammage is given #grammage = float(grammage_str) #thickness = (grammage * 1000) / density #thickness_entry.delete(0, END) #thickness_entry.insert(0, f'{thickness:.2f}') #elif grammage_str and thickness_str: # Update density if both thickness and grammage are provided #thickness = float(thickness_str) #grammage = float(grammage_str) #new_density = grammage / (thickness / 1000) #density_entry.delete(0, END) #density_entry.insert(0, f'{new_density:.2f}') if thickness_str and not grammage_str: #Calculate grammage if only thickness is given thickness = float(thickness_str) grammage = density * thickness / 1000 grammage_entry.delete(0, END) grammage_entry.insert(0, f'{grammage:.2f}') elif grammage_str and not thickness_str: # Calculate thickness if only grammage is given grammage = float(grammage_str) thickness = (grammage * 1000) / density thickness_entry.delete(0, END) thickness_entry.insert(0, f'{thickness:.2f}') elif grammage_str and thickness_str: # Update density if both thickness and grammage are provided thickness = float(thickness_str) grammage = float(grammage_str) new_density = grammage / (thickness / 1000) density_entry.delete(0, END) density_entry.insert(0, f'{new_density:.2f}') if thickness_str and not grammage_str: # Calculate grammage if only thickness is given if thickness_str: thickness = float(thickness_str) grammage = float(density) * thickness / 1000 grammage_entry.delete(0, END) grammage_entry.insert(0, f'{grammage:.2f}') elif grammage_str and not thickness_str: if grammage_str: #Calculate thickness if only grammage is given grammage = float(grammage_str) thickness = (grammage * 1000) / density thickness_entry.delete(0, END) thickness_entry.insert(0, f'{thickness:.2f}') elif grammage_str and thickness_str: # Update density if both thickness and grammage are provided thickness = float(thickness_str) grammage = float(grammage_str) new_density = grammage / (thickness / 1000) density_entry.delete(0, END) density_entry.insert(0, f'{new_density:.2f}') #else: # # Handle the case when both thickness and grammage are filled # grammage_entries[row_num].delete(0, END) # grammage_entries[row_num].insert(0, "") # thickness_entries[row_num].delete(0, END) # thickness_entries[row_num].insert(0,"") else: # Handle the case when density is not provided print("Please enter a valid density value.") except ValueError: # Handle the case when conversion to float fails print("Please enter valid numerical values for Thickness and Grammage.") def on_combobox_select(event, row_num): selected_header = event.widget.get() if selected_header: density_value = df.loc['Density', selected_header] if selected_header else 0 density_entries[row_num].delete(0, END) density_entries[row_num].insert(0, density_value) Specific_heat_capacity_value = df.loc['Specific heat capacity', selected_header] specific_heat_capacity_entries[row_num].delete(0, END) specific_heat_capacity_entries[row_num].insert(0, Specific_heat_capacity_value) Heat_conductivity_value = df.loc['Heat conductivity', selected_header] heat_conductivity_entries[row_num].delete(0, END) heat_conductivity_entries[row_num].insert(0, Heat_conductivity_value) description_value = df.loc['Additional description', selected_header] description_entries[row_num].delete(0, END) description_entries[row_num].insert(0, description_value) # Trigger grammage calculation when density is updated calculate_grammage(row_num, density_value) on_thickness_focus_out(row_num) def on_thickness_focus_out(row_num): density_value = float(density_entries[row_num].get().strip()) if density_entries[row_num].get().strip() else 0 # Trigger grammage calculation when thickness is updated (on focus out) calculate_grammage(row_num, density_value) def delete_row(row_num): if row_num < len(rows): # Remove the row from the list deleted_row = rows.pop(row_num) # Remove the widgets from the grid for widget in deleted_row: widget.grid_forget() # Rearrange the rows after the deleted row for i in range(row_num, len(rows)): for col_index in range(len(column_names) + 2): # Adjust column index for the buttons rows[i][col_index].grid(row=i + 1, column=col_index) # Remove the last empty row if exists if rows and not any(rows[-1]): rows[-1][0].destroy() # Destroy the "Add Row" button rows.pop() # Remove the last empty row from the list def add_row(row_num): # Create a new row with entries, buttons, and delete button items = [] for j in range(len(column_names)): if j == 2: # Material ComboBox material_var = StringVar() material_combobox = ttk.Combobox(layers_window, textvariable=material_var, values=material_names) material_combobox.grid(row=row_num + 1, column=j) density_value = df.loc['Density', material_combobox.get()] if material_combobox.get() else 0 material_combobox.bind("<FocusIn>", lambda event, row=row_num: on_combobox_select(event, row)) items.append(material_combobox) elif j == 3: # Description Entry v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) description_entries.append(entry) elif j == 4: # Grammage Entry v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) grammage_entries.append(entry) grammage_entries[row_num].bind("<FocusIn>", lambda event, row=row_num: on_thickness_focus_out(row)) grammage_entries[row_num].bind("<FocusOut>", lambda event, row=row_num: calculate_grammage(row_num, float( density_entries[ row_num].get().strip()) if density_entries[ row_num].get().strip() else 0)) elif j == 5: # Thickness Entry v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) thickness_entries.append(entry) thickness_entries[row_num].bind("<FocusIn>", lambda event, row=row_num: on_thickness_focus_out(row)) thickness_entries[row_num].bind("<FocusOut>", lambda event, row=row_num: calculate_grammage(row_num, float( density_entries[ row_num].get().strip()) if density_entries[ row_num].get().strip() else 0)) elif j == 6: # Density Entry v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) density_entries.append(entry) # After density entry is created, get the density value for the selected material selected_material = material_combobox.get() density_value = df.loc['Density', selected_material] if selected_material else 0 # Now bind the events with the correct density_value material_combobox.bind("<FocusIn>", lambda event, row=row_num: on_combobox_select(event, row)) thickness_entries[row_num].bind("<FocusIn>", lambda event, row=row_num: on_thickness_focus_out(row)) thickness_entries[row_num].bind("<FocusOut>", lambda event, row=row_num: calculate_grammage(row_num, float( density_entries[ row_num].get().strip()) if density_entries[ row_num].get().strip() else 0)) elif j == 7: # Specific Heat Capacity Entry v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) specific_heat_capacity_entries.append(entry) elif j == 8: # Heat Conductivity Entry v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) heat_conductivity_entries.append(entry) else: # Other Entries v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) # Adjust column index to start from 0 items.append(entry) # Create Add Row and Delete Row buttons add_button = Button(layers_window, text="Add Row", command=partial(add_row, row_num + 1)) add_button.grid(row=row_num + 1, column=len(column_names)) # Adjust column index for the button items.append(add_button) delete_button = Button(layers_window, text="Delete Row",command=partial(delete_row,row_num)) delete_button.grid(row=row_num + 1, column=len(column_names) + 1) # Adjust column index for the button items.append(delete_button) # Shift down the rows below the add button for i in range(len(rows) - 1, row_num - 1, -1): for col_index in range(len(column_names) + 2): # Adjust column index for the buttons rows[i][col_index].grid_forget() # Remove entries and buttons from the grid # Insert the new row at the specified position rows.insert(row_num, items) # Place the entries and buttons back on the grid for i in range(row_num, len(rows)): for col_index in range(len(column_names) + 2): # Adjust column index for the buttons rows[i][col_index].grid(row=i + 1, column=col_index) for col_index, col_name in enumerate(column_names): label = Label(layers_window, text=col_name) label.grid(row=0, column=col_index) for row_num in range(i): items = [] for j in range(len(column_names)): if j == 2: material_var = StringVar() material_combobox = ttk.Combobox(layers_window, textvariable=material_var, values=material_names) material_combobox.grid(row=row_num + 1, column=j) density_value = df.loc['Density', material_combobox.get()] if material_combobox.get() else 0 material_combobox.bind("<FocusIn>", lambda event, row=row_num: on_combobox_select(event, row)) items.append(material_combobox) elif j == 3: v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) description_entries.append(entry) elif j == 4: v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) grammage_entries.append(entry) grammage_entries[row_num].bind("<FocusIn>", lambda event, row=row_num: on_thickness_focus_out(row)) grammage_entries[row_num].bind("<FocusOut>", lambda event, row=row_num: calculate_grammage(row_num, float( density_entries[ row_num].get().strip()) if density_entries[ row_num].get().strip() else 0)) elif j == 5: v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) thickness_entries.append(entry) # Attach on_thickness_focus_out to the thickness entry field's FocusOut event thickness_entries[row_num].bind("<FocusIn>", lambda event, row=row_num: on_thickness_focus_out(row)) thickness_entries[row_num].bind("<FocusOut>", lambda event, row=row_num: calculate_grammage(row_num, float( density_entries[ row_num].get().strip()) if density_entries[ row_num].get().strip() else 0)) elif j == 6: v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) density_entries.append(entry) # After density entry is created, get the density value for the selected material selected_material = material_combobox.get() density_value = df.loc['Density', selected_material] if selected_material else 0 # Now bind the events with the correct density_value material_combobox.bind("<FocusIn>", lambda event, row=row_num: on_combobox_select(event, row)) thickness_entries[row_num].bind("<FocusIn>", lambda event, row=row_num: on_thickness_focus_out(row)) thickness_entries[row_num].bind("<FocusOut>", lambda event, row=row_num: calculate_grammage(row_num, float( density_entries[ row_num].get().strip()) if density_entries[ row_num].get().strip() else 0)) elif j == 7: v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) specific_heat_capacity_entries.append(entry) elif j == 8: v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) items.append(entry) heat_conductivity_entries.append(entry) else: v = StringVar() entry = Entry(layers_window, textvariable=v) v.set(f'Col{j}') entry.grid(row=row_num + 1, column=j) # Adjust column index to start from 0 items.append(entry) # Create a button at the end of the row button = ttk.Button(layers_window, text="Add Row", command=partial(add_row, row_num + 1)) button.grid(row=row_num + 1, column=len(column_names)) # Adjust column index for the button items.append(button) delete_button = ttk.Button(layers_window, text="Delete Row",command=partial(delete_row,row_num)) delete_button.grid(row=row_num + 1, column=len(column_names) + 1) # Adjust column index for the button items.append(delete_button) # Insert the new row at the specified position rows.append(items) setup_ui(layers_window)
both the layers are given the inputs for the materiala new row has been created after clicking add row buttonmaterial in next row after I have added a new row
I would be really grateful if someone can help me in this issue.
I try to change the binding of events or calling of row_num. But it doesn't get solved.