-1
from tkinter import *
import sys

root = Tk()
root.title("To Do")
root.geometry("500x700")

toDoList = []
yAxis = 130

def update_list():
    inputVal = input.get()
    global yAxis
    global todolist
    def delete_to_do():
        global toDoList
        global inputVal
        for item in toDoList:
            if item == inputVal: # <<< NameError is here
                toDoList.remove(inputVal)
        lbl.pack_forget()
        btn.pack_forget()
        frame.pack_forget()

    frame = Frame(root)
    frame.pack()

    lbl = Label(frame, text = input.get())
    lbl.pack(side = "left")

    btn = Button(frame, text = "x", command = delete_to_do)
    btn.pack(side="right")

def add_input():
    global toDoList
    global yAxis
    toDoList.append(input.get())
    yAxis += 35
    print(toDoList)
    update_list()

title = Label(root, text = "To Do", font = ("Comic Sans", 45))
title.pack()

input = Entry(root)
input.pack()

addInput = Button(root, text = "Add", command = add_input)
addInput.pack()

root.mainloop()

In my code I added a comment pointer to show where the NameError is

NameError: name 'inputVal' is not defined
Vladislav Povorozniuc
  • 2,149
  • 25
  • 26
  • where do you define `inputVal` – SuperStew Aug 25 '22 at 13:52
  • I define it at the top of update_list() – Liam Berube Aug 25 '22 at 13:55
  • 1
    why declare it `global` after that – SuperStew Aug 25 '22 at 13:56
  • 2
    Remove all the `global` declarations except for `yAxis`. That's the only one that you actually assign anything to, and some of the other variables aren't actually globals in the first place, which is what's causing an error when you try to access them in the global scope without having defined them there first. – Samwise Aug 25 '22 at 13:56
  • 1
    It's better to avoid using `global` entirely; tkinter provides `Var` classes for sharing and storing mutable data without having to rebind global variables. – Samwise Aug 25 '22 at 13:59
  • 1
    Instead of marking your error in code, show us the __full traceback__ of the error, which tells us where the error is and provides additional information – Pranav Hosangadi Aug 25 '22 at 14:11
  • Use `nonlocal inputVal` instead inside `delete_to_do()`. Or just remove `global inputVal`. – acw1668 Aug 25 '22 at 14:52
  • always put FULL error message (starting at word "Traceback") in question (not in comments) as text (not screenshot, not link to external portal). There are other useful information in the full error/traceback. – furas Aug 25 '22 at 18:58
  • you could use `inputVal = input.get()` directly in `delete_to_do()` without any `global` – furas Aug 25 '22 at 19:01
  • your code always remove last element even if I press middle button - you should keep buttons and labels on list to remove correct widgets. – furas Aug 25 '22 at 19:12

1 Answers1

0

You could use inputVal = input.get() directly in delete_to_do() without any global and it would work.

But all this code has one big mistake. It gets current value from input so button X deletes wrong object on list - it doesn't delete value which is displayed with this button.

Other problem is that variable frame can keep only last created frame and button X can remove only last frame and it can do it only once - so next X may raise error. It would need to keep all frame on list and search which frame to remove - similar to values on todo_list.

But it would be much simpler to use lambda to send value and frame directly to function delete_to_do().

command=lambda:delete_to_do(value, frame)

and later do

def delete_todo(value, frame):
   
    todo_list.remove(value)
    frame.destroy()  # remove from memory because I will NO use it again

    print(todo_list)

Of course this still have some problem: if you add the same element two times then second button will remove first item from list. It would need to keep data as dictionary with unique ID and remove items using this unique ID.


My version with many changes - but still without using unique IDs

import tkinter as tk  # PEP8 `import *` is not proferred

# --- functions ---  # PEP8: all functions before main code

def delete_todo(value, frame):
   
    todo_list.remove(value)  # it removes first matchin value - so it can remove wrong item
    frame.destroy()  # remove from memory because I will NO use it again

    print(todo_list)

def update_list(value):
    frame = tk.Frame(root)
    frame.pack()

    lbl = tk.Label(frame, text=value)  # PEP8: inside `()` use `=` without spaces
    lbl.pack(side="left")

    btn = tk.Button(frame, text="x", command=lambda:delete_todo(value, frame))  # PEP8: inside `()` use `=` without spaces
    btn.pack(side="right")

def add_input():
    global y_axis      # PEP8: space after globals
    #global todo_list  # you don't need `global` if you don't use `=` to assign new value
    
    input_val = input.get()
    
    todo_list.append(input_val)
    y_axis += 35
    
    print(todo_list)
    update_list(input_val)

# --- main ---

todo_list = []  # PEP8: `lower_case_names` for variables

y_axis = 130    # PEP8: `lower_case_names` for variables

root = tk.Tk()
root.title("To Do")
root.geometry("500x700")

title = tk.Label(root, text="To Do", font=("Comic Sans", 45))  # PEP8: inside `()` use `=` without spaces
title.pack()

input = tk.Entry(root)  # there is function `input()` and it would be better to use different variable (but I skip this problem)
input.pack()

add_button = tk.Button(root, text="Add", command=add_input)  # PEP8: inside `()` use `=` without spaces
add_button.pack()

root.mainloop()

PEP 8 -- Style Guide for Python Code

furas
  • 134,197
  • 12
  • 106
  • 148