Python Forum
Button not defined, why?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Button not defined, why?
#1
Hi all,
A newbie to Python & Tkinter here, although have used VB6 & Bash scripts.
Included (hopefully) is my code for a simple sound organiser for use in
a amateur dramatics group I'm involved in.
Idea is start at sound 1, play it then enable sound 2 and disable sound 1
Extra buttons to allow to go back (lots of coding) or forward one sound,
(possible alternative solution) or stop the sound altogether.
Screen shows as required, (button labels to be modified at a later date,)
but pressing Btn1, the attached error happens.
I can't work out why!!!!

Note on draft screen all indents are correct, yet on preview screen all
the indentation is lost. (I Ctrl-C then Ctrl-V the code from my system)

###### CODE ################
#!/usr/bin/python3

from tkinter import *
from tkinter import ttk
from tkinter import font

import os

def window(main, tytle):
# Creates a box positioned centrally
    main.title(tytle)
    main.update_idletasks 
	wydth = ((main.winfo_screenwidth() // 10 ) * 9 )
	#width of box = 9/10 screenwidth
	hite = ((main.winfo_screenheight() // 5 ) * 4)
	#height of box = 4/5 screenheight
	x = (main.winfo_screenwidth() // 2  ) -  (wydth // 2 )
	# x posn of box is 1/2 screen width minus 1/2 box width
	y = (main.winfo_screenheight() // 2  ) -  ( hite // 2 )
	# y posn of box = 1/2 screen height minus 1/2 box height
	main.geometry('{}x{}+{}+{}'.format(wydth, hite,  x, y ))

def btn_press():
	print("it's working")
	if Btn1.cget('bg') == "yellow":
		print("1 is yellow")
		os.system('/usr/bin/mpg321 /home/john/Music/Sounds/sound1.mp3 &')
		Btn1.configure( bg = "green", state=DISABLED)
		Btn2.configure( bg = "yellow", state=NORMAL)
	elif Btn2.cget('bg') == "yellow":
		print("2 is yellow")
		os.system('/usr/bin/mpg321 /home/john/Music/Sounds/sound2.mp3 &')
		Btn2.configure( bg = "green", state=DISABLED)
		Btn3.configure( bg = "yellow", state=NORMAL)
	elif Btn3.cget('bg') == "yellow":
		print("3 is yellow")
		os.system('/usr/bin/mpg321 /home/john/Music/Sounds/sound3.mp3 &')
		Btn3.configure( bg = "green", state=DISABLED)
		Btn4.configure( bg = "yellow", state=NORMAL)
	elif Btn4.cget('bg') == "yellow":
		print("4 is yellow")
		os.system('/usr/bin/mpg321 /home/john/Music/Sounds/sound4.mp3 &')
		Btn4.configure( bg = "green", state=DISABLED)
		Btn5.configure( bg = "yellow", state=NORMAL)
	elif Btn5.cget('bg') == "yellow":
		print("5 is yellow")
		os.system('/usr/bin/mpg321 /home/john/Music/Sounds/sound5.mp3 &')
		Btn5.configure( bg = "green", state=DISABLED)
		Btn6.configure( bg = "yellow", state=NORMAL)
	else:
		print("6 is yellow")
		os.system('/usr/bin/mpg321 /home/john/Music/Sounds/sound6.mp3 &')
		Btn6.configure( bg = "green", state=DISABLED)
		Btn1.configure( bg = "yellow", state=NORMAL)
		
def back_one():
	print("Go back one button")
	stop_mp3()
	if Btn6.cget('bg') == "yellow":
		print("6 is yellow")
		Btn6.configure( bg = "green", state=DISABLED)
		Btn5.configure( bg = "yellow", state=NORMAL)
	elif Btn5.cget('bg') == "yellow":
		print("5 is yellow")
		Btn5.configure( bg = "green", state=DISABLED)
		Btn4.configure( bg = "yellow", state=NORMAL)
	elif Btn4.cget('bg') == "yellow":
		print("4 is yellow")
		Btn4.configure( bg = "green", state=DISABLED)
		Btn3.configure( bg = "yellow", state=NORMAL)
	elif Btn3.cget('bg') == "yellow":
		print("3 is yellow")
		Btn3.configure( bg = "green", state=DISABLED)
		Btn2.configure( bg = "yellow", state=NORMAL)
	elif Btn2.cget('bg') == "yellow":
		print("2 is yellow")
		Btn2.configure( bg = "green", state=DISABLED)
		Btn1.configure( bg = "yellow", state=NORMAL)
	elif Btn1.cget('bg') == "yellow":
		print("1 is yellow")
		Btn1.configure( bg = "green", state=DISABLED)
		Btn6.configure( bg = "yellow", state=NORMAL)
	
def stop_mp3():
	print("Stop the mp3")
	os.system('psnum=$(ps -aef | grep mpg321) ; psnum=$(echo ${psnum#*" "}) ; psnum=$(echo ${psnum%%" "*}) ; kill $psnum ')

def fwd_one():
	print("Go forward one")
	stop_mp3()
	list = ["Btn1.cget('bg')","Btn2.cget('bg')","Btn3.cget('bg')","Btn4.cget('bg')","Btn5.cget('bg')", "Btn6.cget('bg')"]
	for item in list:
		#print(item)
		if item == "yellow":
			print(item +" is it")
			break
		else:
			print(item)
	
# root is the main window that surrounds the interface
# This creates a Tk object
root = Tk()

helv36 = font.Font(family="Helvetica",size=36,weight="bold")
helv14 = font.Font(family="Helvetica",size=14,weight="bold")

def btn_creation():
	list = ['Btn1','Btn2','Btn3','Btn4','Btn5','Btn6','Btn7','Btn8','Btn9']
	rctr=0
	cctr=0
	stayt=NORMAL
	btncmd=btn_press
	bgcol="yellow"
	for item in list:
		item = Button(root, text=item, height=3, width=14, fg = "black" , bg = bgcol, activebackground = "red", font = helv36 , state=stayt, command=btncmd)
		item.grid(row=rctr, column=cctr)
		cctr=cctr+1
		bgcol="green"
		if cctr == 3 :
			cctr=0
			rctr=rctr+1
		if rctr != 2:
			stayt=DISABLED
		if rctr == 2:
			bgcol="white"
			stayt=NORMAL
			if cctr == 0:
				btncmd=back_one
			if cctr == 1:
				btncmd=fwd_one
				bgcol="blue"
				


# Call the above function
window(root, "Sound maker")

btn_creation()

# This keeps the root window visible
# and the program running
root.mainloop()
###### ERROR FROM CLI ##############
Error:
john@john-HP:~$ Sound_mkr.py it's working Exception in Tkinter callback Traceback (most recent call last): File "/usr/lib/python3.5/tkinter/__init__.py", line 1562, in __call__ return self.func(*args) File "/home/john/bin/Sound_mkr.py", line 25, in btn_press if Btn1.cget('bg') == "yellow": NameError: name 'Btn1' is not defined
Reply
#2
At first glance, I see two problems in the code:
1. Button creation function. By using a list of strings, you aren't actually creating buttons called 'Btn1', 'Btn2', and so on. You're making a list of buttons, and maybe not even that- I'm not sure you can redefine list items in a loop based on that list. If you want to make buttons with their own names, they need to be defined individually.
2. Variable creation. When you define your btn_press function, you're using a variable that doesn't exist yet. You can't do things out of order like that unless you do it within a class.
Reply
#3
Not sure of the whole problem you have but here is a snippet from a program I wrote to create a bunch of buttons.
ro = 1
line = 1
colcount = 10
for x in range(1,56):
        txt = str(x)
        myname="button" + txt
        myname = Button(frame3, text = txt, font = 30, width = 3)
        myname.bind('<Button-1>', play_song)
        myname.grid(row = ro, column = line)
        line += 1
        if line == colcount:
            line = 1
            ro += 1
the name of the buttons will be button1, button2 etc and the text on the corresponding button will be 1,2 and so on.
Maybe that will be of use in solving part of your problem
Reply
#4
@Johnny
1. Don't use python keywords as variables.
list = ['btn1', 'btn2', etc]
2. You can't use string as variables and making variables in functions are local only.
You have to pass them to other functions.
Something like this. buttons[0] - buttons[8]
def button_creation():
    buttons = []
    # other code
    for n in xrange(9):
        #new button
        buttons.append(Button(etc))
        buttons[-1].grid(etc)
    return buttons
@Barrowman
3.
# this get replace by next line
myname = "button" + txt # string
mayname = Button(etc) # delete string and now a tk.Button
99 percent of computer problems exists between chair and keyboard.
Reply
#5
@Windspar
I understand what you are saying but I believe you are mistaken because although Button is a keyword
button isn't nor is button1 a python keyword any more than btn1 is a keyword.
for example:
button25 = button(frame4,text = "  Help  ", font = TF, background = bcol)
produces the error:
Quote:Traceback (most recent call last):
  File "./sign-songsPC-plus15.py", line 227, in <module>
    button25 = button(frame4,text = "  Help  ", font = TF, background = bcol)
NameError: name 'button' is not defined
Reply
#6
Quote:buttons.append(Button(etc))
in his example buttons is a list of tkinter.Button objects.

Quote:list = ['btn1', 'btn2', etc]
If your listing out wishing the variables names to be btn1 and btn2...whats the point? you might as well stick them in a list and identify them by index anyways. buttons[0] will be the first and so on.

If you actually want to make custom names, just use a dictionary
buttons['exit'] and so on.
Recommended Tutorials:
Reply
#7
Let see if this clear it up
import tkinter as tk

def create_buttons():
    buttons_name = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
    buttons = []
    
    for name in buttons_name:
        buttons.append(tk.Button(text=name))
        
    return buttons
    
def main():
    buttons = create_buttons()
    for button in buttons:
        print(button['text'])
    print('')
    print('button 3:', buttons[3]['text']) # four will be the answer
99 percent of computer problems exists between chair and keyboard.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [Kivy] Acces atributes from a button defined in a class inside the .kv Tomli 2 2,052 Jun-10-2021, 01:05 AM
Last Post: Tomli
  [PySimpleGui] How to alter mouse click button of a standard submit button? skyerosebud 3 4,948 Jul-21-2019, 06:02 PM
Last Post: FullOfHelp
  [Tkinter] button not defined OldManProgrammer 2 4,446 Nov-21-2018, 07:53 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020