nozzy
nozzy

Reputation: 33

How do I get return self.func(*args) to work in Tkinter Python?

I have just started my first Python project (sorry if this is a dumb question I am just starting out) and am using the Tkinter interface. I seem to keep on receiving this prompt:

Exception in Tkinter callback Traceback (most recent call last): File "D:\Apps\Python\lib\tkinter_init_.py", line 1883, in call return self.func(*args) File "c:/Users/noahc/Documents/Programming/AppLauncher/AppLauncher.py", line 62, in resetList = tk.Button(root, text="Reset", padx=10, pady=5, fg="white", bg="#263D42", command=lambda:[removeSave(),resetList()]) TypeError: 'Button' object is not callable

I have provided the code below:

#########################
# CREATED BY NOZZYPOZZY #
#########################
import tkinter as tk
from tkinter import filedialog, Text
import os

root = tk.Tk()

root.title("App Launcher")
root.iconbitmap('C:/Users/noahc/Documents/Programming/AppLauncher/icon.ico')
root.resizable(0,0)

apps = []

if os.path.isfile('save.txt'):
    with open('save.txt','r') as f:
        tempApps = f.read()
        tempApps = tempApps.split(',')
        apps = tempApps
        apps = [x for x in tempApps if x.strip()]


def addApp():

    for widget in frame.winfo_children():
        widget.destroy()

    filename = filedialog.askopenfilename(initialdir="/", title="Select File", filetypes=(("Executables","*.exe"), ("All Files", "*.*")))\

    apps.append(filename)
    print(filename)
    for app in apps:
        label = tk.Label(frame, text=app, bg="gray")
        label.pack()

def runApps():
    for app in apps:
        os.startfile(app)

def resetList():
    for widget in frame.winfo_children():
        widget.destroy()

def removeSave():
    os.remove('save.txt')



canvas = tk.Canvas(root, height=700, width=700, bg="gray")
canvas.pack()

frame = tk.Frame(root, bg="white")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1)

openFile = tk.Button(root, text="Open File", padx=10, pady=5, fg="white", bg="#263D42", command=addApp)
openFile.pack()

runApps = tk.Button(root, text="Run Apps", padx=10, pady=5, fg="white", bg="#263D42", command=runApps)
runApps.pack()

resetList = tk.Button(root, text="Reset", padx=10, pady=5, fg="white", bg="#263D42", command=lambda:[removeSave(),resetList()])
resetList.pack()




for app in apps:
    label = tk.Label(frame, text=app)
    label.pack()

root.mainloop()


with open('save.txt', 'w') as f:
    for app in apps:
        f.write(app + ',')

Upvotes: 0

Views: 8910

Answers (2)

nozzy
nozzy

Reputation: 33

I suppose you mean that after you hit reset, then "Open File" and it populates your list with the previous entries? When you execute resetList, you just remove the items from the display, but keep your apps list populated, so when you call addApp, this list is loaded and displayed again with the new element at the end. You could fix that by calling apps.clear() in your resetList function, which will delete all entries in apps. – answer by @Talon

Upvotes: 0

Talon
Talon

Reputation: 1884

Your function resetList shares a name with your Button variable. Instead of your function, it tries to call itself.

On this line:

resetList = tk.Button(root, text="Reset", padx=10, pady=5, fg="white", bg="#263D42", command=lambda:[removeSave(),resetList()])

You're using the lambda function to execute the function removeSave and resetList. The problem is that the variable you're assigning this button too is also called resetList. We can check that when we replace the function call and instead print out what resetList is:

resetList = tk.Button(root, text="Reset", padx=10, pady=5, fg="white", bg="#263D42", command=lambda:[removeSave(),print(repr(resetList))])

Upon execution this will give us <tkinter.Button object .!button3> You called your function resetList, but overwrote that with the button that is also called resetList, so instead of executing the function with resetList(), your program tries to execute the button. You can fix that for example by renaming your Button variable, e.g.:

reset_list_button = tk.Button(root, text="Reset", padx=10, pady=5, fg="white", bg="#263D42", command=lambda:[removeSave(),resetList()])
reset_list_button.pack()

Upvotes: 3

Related Questions