-2

I'm trying to make a simple colour game in Tkinter, and here is what I have coded so far:

from tkinter import *

import sys

import random

window = Tk() # initialize the window
window.geometry("653x500+78+78")
window.title("Welcome to Color Game!")


c = Canvas(window, height = 500, width = 653, highlightthickness = 0)# adding bg to test if the canvas is in the window
c.pack()

instructions = """          Welcome to Color Game! In this game, you will see a word on the screen. It will be
a color, like red.

         All you have to do is type in the COLOR of the word, not the word itself. So if the word is red, but the

text color is green, then you have to type green in. You will see the word for 1.5 seconds, which is enough time
to see a word and for your brain to identify a color. Enjoy!!!

         Oh yeah, and if you enter the actual word, you actually lose points :D
"""

text = c.create_text(325, 100, text = instructions, font = ("Helvetica", 10))



def start(): #this will be where the main game happens
    second = 2000
    
    window.withdraw()# close main menu
    #Here we configure the window boi
    main = Tk()
    main.geometry("653x500+78+78")
    main.title("Enter the color of the word, not the word itself")
    main.focus_force()
    main.configure(bg = "white")

    colors = ["Red", "Blue", "Green", "Orange", "Purple", "Brown", "Yellow"]

    choose = colors.copy()# copying the list so we can alter the elements without actually muting the original list. 
    
    text_color = random.choice(choose)
    choose.remove(text_color)
    actual_color = random.choice(choose)

    text = Label(main, text = text_color, fg = actual_color, bg = "white", font = ("Helvetica", 20))
    text.place(relx = 0.5, rely = 0.5, anchor = "center")

    count_down = Label(main, text = int(int(second)/1000), fg = random.choice(colors), bg = "white", font = ("Helvetica", 20))
    count_down.place(relx = 0.5, rely = 0.25, anchor = "center")
    second -= 1000

    main.after(1000, start)
    
def nevermind():# nevermind function. Status done
    window.withdraw()
    last = Tk()
    last.geometry("350x200")
    last.title("Are you sure?")
    t = Label(last, text = "Don't Quit! Quitting is for NOOBS!")
    t.place(relx = 0.5, rely = 0.45, anchor = "center")

    lastt = Label(last, text = "Are you sure?")
    lastt.place(relx = 0.5, rely = 0.55, anchor = "center")

    def YES():
        last.destroy()
        window.deiconify()
    
    yes = Button(last, text = "Yes", command = quit)
    no = Button(last, text = "No", command = YES)
    yes.place(relx = 0.25, rely = 0.95, relwidth = 0.5, relheight = 0.1, anchor = "center")
    no.place(relx = 0.75, rely = 0.95, relwidth = 0.5, relheight = 0.1, anchor = "center")
    

#add a start button and a nevermind button ;D
start = Button(window, text = "Start Game!", bd = 0, highlightthickness = 0, bg = "powder blue", activebackground = "powder blue", command = start)
start.place(relx = 0.25, rely = 0.95, relwidth = 0.5, relheight = 0.1, anchor = "center")

never_mind = Button(window, text = "Never mind!", bd = 0, highlightthickness = 0, bg = "orange", activebackground = "orange", command = nevermind)
never_mind.place(relx = 0.75, rely = 0.95, relwidth = 0.5, relheight = 0.1, anchor = "center")

window.mainloop() #always add this :D

Here is the function specific to the error I am getting:

def start(): #this will be where the main game happens
    second = 2000
    
    window.withdraw()# close main menu
    #Here we configure the window boi
    main = Tk()
    main.geometry("653x500+78+78")
    main.title("Enter the color of the word, not the word itself")
    main.focus_force()
    main.configure(bg = "white")

    colors = ["Red", "Blue", "Green", "Orange", "Purple", "Brown", "Yellow"]

    choose = colors.copy()# copying the list so we can alter the elements without actually muting the original list. 
    
    text_color = random.choice(choose)
    choose.remove(text_color)
    actual_color = random.choice(choose)

    text = Label(main, text = text_color, fg = actual_color, bg = "white", font = ("Helvetica", 20))
    text.place(relx = 0.5, rely = 0.5, anchor = "center")

    count_down = Label(main, text = int(int(second)/1000), fg = random.choice(colors), bg = "white", font = ("Helvetica", 20))
    count_down.place(relx = 0.5, rely = 0.25, anchor = "center")
    second -= 1000

    main.after(1000, start)

But I am getting the error:

>   main.after(1000, start)
  File "C:\Users\offcampus\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 611, in after
    callit.__name__ = func.__name__
AttributeError: 'Button' object has no attribute '__name__'

I have looked at this question, but I am honestly confused because I am not assigning any attribute whatsoever to the Button class.

So what is going on here?

Barmar
  • 741,623
  • 53
  • 500
  • 612
10 Rep
  • 2,217
  • 7
  • 19
  • 33
  • 2
    Also read [Why are multiple instances of Tk discouraged?](https://stackoverflow.com/questions/48045401/why-are-multiple-instances-of-tk-discouraged) – Henry Yik Sep 04 '20 at 04:19
  • The error occurs because, as part of implementing the `.after` logic, *Tkinter* needs to assign an attribute that your `Button` doesn't have. The *real* clue is that you weren't expecting any of the things mentioned in your code to be a `Button`, but one of them (specfically, `start`) is. – Karl Knechtel Sep 04 '20 at 04:20
  • But yes, if you are using `.after` recursively to create game loop, you should not be creating your Tk instance *inside* that loop. – Karl Knechtel Sep 04 '20 at 04:21
  • @HenryYik I understand the issue now. – 10 Rep Sep 04 '20 at 04:39
  • @KarlKnechtel Yes, I understand and I have fixed the code a little. – 10 Rep Sep 04 '20 at 04:39

1 Answers1

4

You're reusing the name start here:

start = Button(window, text = "Start Game!", bd = 0, highlightthickness = 0, bg = "powder blue", activebackground = "powder blue", command = start)

So when you call main.after(1000, start) it's trying to use that button, but the second argument to main.after() needs to be a function.

Don't use the same name for a variable and a function -- rename the variable used for the Start Game button, or rename the function.

Barmar
  • 741,623
  • 53
  • 500
  • 612