Tkinter widget is not updating based on inputs? - python

I have created a widget in python using tkinter library. It has one combobox
from tkinter import *
from tkinter.ttk import *
import os
import time
import win32api
def f_step():
window=Tk()
style = Style()
style.configure('W.TButton', font =
('calibri', 12, 'bold'),
foreground = 'blue')
s = Style() # Creating style element
s.configure('Wild.TRadiobutton', # First argument is the name of style. Needs to end with: .TRadiobutton
background='bisque2', # Setting background to our specified color above
font = "calibri 10 bold") # You can define colors like this also
window.title('Tool tool')
window.geometry("700x300+10+10")
#window.geometry(side="top", fill="both", expand = True)
txt_1=StringVar()
lbl_1 = Label(window,text="Are result files same", background ="bisque2",font = "calibri 10 bold").place(x=10,y=40)
lbl_2 = ttk.Combobox(window,textvariable = txt_1, values = ["Yes","No"], background ="bisque2",font = "calibri 10 bold").place(x=275,y=40)
a1 = txt_1.get()
if a1 == "Yes":
txt_2=StringVar()
lbl_3 = Label(window,text="Working directory path", background ="bisque2",font = "calibri 10 bold").place(x=10,y=70)
txt_b = Entry(window,textvariable=txt_2,width=60).place(x=275,y=70)
txt_3=StringVar()
lbl_4 = Label(window,text="file name (without extenstion)", background ="bisque2",font = "calibri 10 bold").place(x=10,y=100)
txt_c = Entry(window,textvariable=txt_2,width=60).place(x=275,y=100)
elif a1 == "No":
txt_2=StringVar()
lbl_3 = Label(window,text="Working directory path", background ="bisque2",font = "calibri 10 bold").place(x=10,y=70)
txt_b = Entry(window,textvariable=txt_2,width=60).place(x=275,y=70)
txt_3=StringVar()
lbl_4 = Label(window,text="file1 name (without extenstion)", background ="bisque2",font = "calibri 10 bold").place(x=10,y=100)
txt_c = Entry(window,textvariable=txt_2,width=60).place(x=275,y=100)
txt_4=StringVar()
lbl_5 = Label(window,text="file2 name (without extenstion)", background ="bisque2",font = "calibri 10 bold").place(x=10,y=130)
txt_d = Entry(window,textvariable=txt_2,width=60).place(x=275,y=130)
btn_1 = Button(window, text="run",style = 'W.TButton',command=clicked)
btn_1.place(x=300,y=250)
window.configure(bg='bisque2')
window.resizable(0, 0)
window.mainloop()
def clicked():
a=1212
f_step()
It has combobox but once i select one option (yes or no) it does not update the following options. Please help me to solve this as i am not sure how to update the application based on real time inputs. i do not want it to updated once i click the button. Also this is just the portion of code which i am having the problem please advise.

You should bind the virtual event <<ComboboxSelected>> to a callback and show the required labels and entries based on the combobox selection in the callback:
def f_step():
window = Tk()
window.title('Tool tool')
window.geometry("700x300+10+10")
#window.geometry(side="top", fill="both", expand = True)
window.configure(bg='bisque2')
window.resizable(0, 0)
s = ttk.Style() # Creating style element
s.configure('W.TButton', font=('calibri', 12, 'bold'), foreground='blue')
s.configure('Wild.TRadiobutton', # First argument is the name of style. Needs to end with: .TRadiobutton
background='bisque2', # Setting background to our specified color above
font="calibri 10 bold") # You can define colors like this also
def on_change(event):
# show the labels and entries
lbl_3.place(x=10, y=70)
txt_b.place(x=275, y=70)
lbl_4.place(x=10, y=100)
txt_c.place(x=275, y=100)
a1 = txt_1.get()
if a1 == "Yes":
lbl_5.place_forget()
txt_d.place_forget()
else:
lbl_5.place(x=10, y=130)
txt_d.place(x=275, y=130)
txt_1 = StringVar()
Label(window, text="Are result files same", background ="bisque2", font="calibri 10 bold").place(x=10,y=40)
cb_1 = ttk.Combobox(window, textvariable=txt_1, values=["Yes","No"], background="bisque2", font="calibri 10 bold", state="readonly")
cb_1.place(x=275,y=40)
cb_1.bind("<<ComboboxSelected>>", on_change)
# define the labels and entries and initially they are hidden
txt_2 = StringVar()
lbl_3 = Label(window, text="Working directory path", background="bisque2", font="calibri 10 bold")
txt_b = Entry(window, textvariable=txt_2, width=60)
txt_3 = StringVar()
lbl_4 = Label(window, text="file1 name (without extenstion)", background="bisque2", font="calibri 10 bold")
txt_c = Entry(window, textvariable=txt_3, width=60)
txt_4 = StringVar()
lbl_5 = Label(window, text="file2 name (without extenstion)", background="bisque2", font="calibri 10 bold")
txt_d = Entry(window, textvariable=txt_4, width=60)
btn_1 = ttk.Button(window, text="run", style='W.TButton', command=clicked)
btn_1.place(x=300, y=250)
window.mainloop()
Note that your code uses txt_2 variable in txt_c and txt_d entries and I think it is typo and fix it.

what you are looking for is lbl_2.bind("<<ComboboxSelected>>", f_step) also note that you must add a parameter in the f_step function as it is passed form combo virtual event. This will make sure to update whenever the option is changed
Try this:
from tkinter import *
from tkinter.ttk import *
import os
import time
import win32api
def f_step(event=None):
a1 = txt_1.get()
if a1 == "Yes":
txt_2=StringVar()
lbl_3 = Label(window,text="Working directory path", background ="bisque2",font = "calibri 10 bold").place(x=10,y=70)
txt_b = Entry(window,textvariable=txt_2,width=60).place(x=275,y=70)
txt_3=StringVar()
lbl_4 = Label(window,text="file name (without extenstion)", background ="bisque2",font = "calibri 10 bold").place(x=10,y=100)
txt_c = Entry(window,textvariable=txt_2,width=60).place(x=275,y=100)
elif a1 == "No":
txt_2=StringVar()
lbl_3 = Label(window,text="Working directory path", background ="bisque2",font = "calibri 10 bold").place(x=10,y=70)
txt_b = Entry(window,textvariable=txt_2,width=60).place(x=275,y=70)
txt_3=StringVar()
lbl_4 = Label(window,text="file1 name (without extenstion)", background ="bisque2",font = "calibri 10 bold").place(x=10,y=100)
txt_c = Entry(window,textvariable=txt_2,width=60).place(x=275,y=100)
txt_4=StringVar()
lbl_5 = Label(window,text="file2 name (without extenstion)", background ="bisque2",font = "calibri 10 bold").place(x=10,y=130)
txt_d = Entry(window,textvariable=txt_2,width=60).place(x=275,y=130)
def clicked():
a=1212
#f_step()
window=Tk()
style = Style()
style.configure('W.TButton', font =
('calibri', 12, 'bold'),
foreground = 'blue')
s = Style() # Creating style element
s.configure('Wild.TRadiobutton', # First argument is the name of style. Needs to end with: .TRadiobutton
background='bisque2', # Setting background to our specified color above
font = "calibri 10 bold") # You can define colors like this also
window.title('Tool tool')
window.geometry("700x300+10+10")
#window.geometry(side="top", fill="both", expand = True)
txt_1=StringVar()
lbl_1 = Label(window,text="Are result files same", background ="bisque2",font = "calibri 10 bold").place(x=10,y=40)
lbl_2 = Combobox(window,textvariable = txt_1, values = ["Yes","No"], background ="bisque2",font = "calibri 10 bold")
lbl_2.place(x=275,y=40)
#lbl_2.current(1)
lbl_2.bind("<<ComboboxSelected>>", f_step)
btn_1 = Button(window, text="run",style = 'W.TButton',command=clicked)
btn_1.place(x=300,y=250)
window.configure(bg='bisque2')
window.resizable(0, 0)
window.mainloop()
also if you want to update only when run is clicked you may call the f_step from clicked() and remove the binding from combobox.
ok as per your request here is the Updated code:
from tkinter import *
from tkinter.ttk import *
import os
import time
import win32api
def f_step(event=None):
global lbl_3
global txt_b
global lbl_4
global lbl_c
global lbl_5
global txt_d
hide()
a1 = txt_1.get()
txt_2=StringVar()
txt_3=StringVar()
lbl_3 = Label(window,text="Working directory path", background ="bisque2",font = "calibri 10 bold")
lbl_3.place(x=10,y=70)
txt_b = Entry(window,textvariable=txt_2,width=60)
txt_b.place(x=275,y=70)
txt_b = Entry(window,textvariable=txt_2,width=60)
txt_b.place(x=275,y=70)
lbl_4 = Label(window,text="file name (without extenstion)", background ="bisque2",font = "calibri 10 bold")
lbl_4.place(x=10,y=100)
txt_c = Entry(window,textvariable=txt_2,width=60)
txt_c.place(x=275,y=100)
if a1 == "No":
lbl_5 = Label(window,text="file2 name (without extenstion)", background ="bisque2",font = "calibri 10 bold")
lbl_5.place(x=10,y=130)
txt_d = Entry(window,textvariable=txt_2,width=60)
txt_d.place(x=275,y=130)
def hide():
#lbl_3.place_forget()
lbl_3.destroy()
txt_b.destroy()
lbl_4.destroy()
txt_c.destroy()
lbl_5.destroy()
txt_d.destroy()
def clicked():
a=1212
f_step()
window=Tk()
style = Style()
style.configure('W.TButton', font =
('calibri', 12, 'bold'),
foreground = 'blue')
s = Style() # Creating style element
s.configure('Wild.TRadiobutton', # First argument is the name of style. Needs to end with: .TRadiobutton
background='bisque2', # Setting background to our specified color above
font = "calibri 10 bold") # You can define colors like this also
window.title('Tool tool')
window.geometry("700x300+10+10")
lbl_3 = Label(window)
txt_b = Entry(window)
txt_b = Entry(window)
lbl_4 = Label(window)
txt_c = Entry(window)
lbl_5 = Label(window)
txt_d = Entry(window)
txt_1=StringVar()
lbl_1 = Label(window,text="Are result files same", background ="bisque2",font = "calibri 10 bold").place(x=10,y=40)
lbl_2 = Combobox(window,textvariable = txt_1, values = ["Yes","No"], background ="bisque2",font = "calibri 10 bold")
lbl_2.place(x=275,y=40)
#lbl_2.current(1)
lbl_2.bind("<<ComboboxSelected>>", f_step)
btn_1 = Button(window, text="run",style = 'W.TButton',command=clicked)
btn_1.place(x=300,y=250)
window.configure(bg='bisque2')
window.resizable(0, 0)
window.mainloop()
you can use the widget.destroy() to delete the widget whole together or widget.place_forget to temporarily hide the widget. Note: if you use widget.place_forget you don't need to recreate the widget instead change the existing widget using widget.config

Related

Variable not defined / function not defined

I am trying to code a CPS test for fun but I ran into a problem:
I defined a function at the beginning of the code and than I defined a tkinter button which has this function as command and the button should disappear in this function. When I do it like this it says that the variable of the button isn't defined yet but when I defined it vice versa so first the button and then the function it says that the function is not defined yet.
Can anyone help me?
(Sorry for my bad English)
import tkinter as tk
root = tk.Tk()
root.title("CPS test")
root.geometry("1000x1000")
root.configure(bg='white')
def getstring():
duration = entry.get()
entry.delete(0)
entry.place_forget()
okbutton.place_forget
lab1 = tk.Label(text = "How long should the CPS test last? 2,5 or 10 seconds?(Answer with 2,5,10)", font = "Ariel 20", bg = "#FFFFFF")
button = tk.Button(root, text = "Click me!", font = "Ariel 50", bg = "#FFFFFF", fg = "#000000")
entry = tk.Entry(root, font=('Arieal 20'), bd = 2)
okbutton = tk.Button(root, text = "OK", font = "Ariel 20", bg = "#FFFFFF", fg = "#000000", bd = 2, command = getstring())
lab1.place(x = 45,y = 250)
entry.place(x = 344, y = 350)
entry.insert(0, "Enter your answer here!")
okbutton.place(x = 465, y = 400)
root.mainloop()
I think the error is on the button name.
def getstring():
duration = entry.get()
entry.delete(0)
entry.place_forget()
button.place_forget
Just replace "okbutton" by "button" and it should work.
Else just declared the "okbutton" before the function

Image not appearing in Ttkinter window

What I'm trying to do is to display the image cover from a flac file like in the pic below (this one is hard coded).
I ripped the cover with the function getCoverFlac from my code, but the problem begins when I try to update this img with my imgSet fucntion, the image to load exist(can see it in the dir and can even be used hard coded), but the image wont appear in the Ttkinter window. I believe its receiving the right file name since it returns the name correctly:
name of cover to display:Shikao Suga - Yuudachi ('99 NHK Hall 0 Live).flacCover.jpg
so how can I fix this?
full code bellow:
import pygame
import tkinter as tkr
from tkinter.filedialog import askdirectory
from tkinter import *
import os
from mutagen.flac import FLAC, Picture
import os.path
from PIL import ImageTk, Image
music_player = tkr.Tk()
cont = 0
music_player.title("My Music Player")
music_player.geometry("600x600")
play_list = tkr.Listbox(music_player, font="Helvetica 12 bold", bg='yellow', selectmode=tkr.SINGLE)
pygame.init()
pygame.mixer.init()
def play():
pygame.mixer.music.load(play_list.get(tkr.ACTIVE))
#gets and set the var name
var.set(play_list.get(tkr.ACTIVE))
#gets the cover and sets the the img that will be in panel
getThecover = getCoverFlac(play_list.get(tkr.ACTIVE))
imgSet(getThecover)
pygame.mixer.music.play()
def stop():
pygame.mixer.music.stop()
def pause():
pygame.mixer.music.pause()
def unpause():
pygame.mixer.music.unpause()
def selectDir():
directory = askdirectory()
os.chdir(directory)
song_list = os.listdir()
for item in song_list:
pos = 0
play_list.insert(pos, item)
pos += 1
def getCoverFlac(flac_file):
#this fucntion extracts the image from the flac file and saves it in the dir where the flac file is.
flacObj = FLAC(flac_file)
coverArt = flacObj.pictures
coverName = str(flac_file)+"Cover.jpg"
if os.path.isfile(coverName):
print(coverName+" already exists")
else:
for img in coverArt:
if img.type == 3:
with open(coverName, "wb") as f:
f.write(img.data)
print(coverName+" created and saved")
#img.show()
return coverName
def imgSet(var):
#sets the global var "img" to var
global img
print("name of cover to display:"+var)
resizeImg(var)
img = ImageTk.PhotoImage(Image.open(var))
def resizeImg(imgName):
basewidth = 300
img = Image.open(imgName)
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save(imgName)
Button1 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="PLAY", command=play, bg="blue", fg="white")
Button2 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="STOP", command=stop, bg="red", fg="white")
Button3 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="PAUSE", command=pause, bg="purple", fg="white")
Button4 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="UNPAUSE", command=unpause, bg="orange", fg="white")
Button5 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="Music Dir", command=selectDir, bg="green", fg="white")
var = tkr.StringVar()
song_title = tkr.Label(music_player, font="Helvetica 12 bold", textvariable=var)
resizeImg('Haddaway - What Is Love (70 Mix).flacCover.jpg')
img = ImageTk.PhotoImage(Image.open('Haddaway - What Is Love (70 Mix).flacCover.jpg'))
panel = tkr.Label(music_player, image = img, justify=CENTER)
song_title.pack()
panel.pack(fill="x")
Button1.pack(fill="x")
Button2.pack(fill="x")
Button3.pack(fill="x")
Button4.pack(fill="x")
Button5.pack(fill="x")
play_list.pack(fill="both", expand="yes")
music_player.mainloop()
You just update the global variable img inside imageSet(), but forget to update the image of the label using panel.config(image=img):
def imgSet(var):
#sets the global var "img" to var
global img
print("name of cover to display:"+var)
resizeImg(var)
img = ImageTk.PhotoImage(Image.open(var))
panel.config(image=img) # update image of label "panel"

make tkinter window shrink, as widgets are deleted

I'm making some program, where I input a bunch of stuff into an entry and it gets printed into a row. I also added a feature where you can delete a row. However, when I delete a row, the window does not shrink. The way I actually made the program was by having 2 frames; the main frame with the buttons and entries, and the output or text frame. When I delete a row, it actually appends the data from a list, deletes the frame and all the widgets and reprints the rows, but with out the row I deleted.
The issue with my code, is that when I delete a row, the rows that weren't deleted start to get smaller and compress and secondly, the bottom of the window doesn't move upwards, leaving a blank white space.
Any help would be appreciated, thanks.
actually appending, labelling and printing the row is in function append_entry() and my delete function is delete_row()
from tkinter import *
global main_window
def quit():
main_window.destroy()
def entry_labels():
leader_label = Label(main_frame, text = 'Customer Name')
leader_label.grid(column=0, row=0)
location_label = Label(main_frame, text = 'Receipt Number')
location_label.grid(column=0, row=1)
numcampers_label = Label(main_frame, text = 'Item Hired')
numcampers_label.grid(column=0, row=2)
weather_label = Label(main_frame, text = 'Number Hired')
weather_label.grid(column=0, row=3)
row_label = Label(main_frame, text= 'Row')
row_label.grid(column=3, row=2)
def button():
print_button = Button(main_frame, text = "Print Details", command = append_entry)
print_button.grid(column=3, row=1)
quit_button = Button(main_frame, text= "Quit", command=quit)
quit_button.grid(column=4, row=0)
delete_row_button = Button(main_frame, text = 'Delete Row', command = delete_row)
delete_row_button.grid(column=4, row=3)
def entry():
global name_entry
name_entry = Entry(main_frame)
name_entry.grid(column=1, row=0)
global receipt_entry
receipt_entry = Entry(main_frame)
receipt_entry.grid(column=1, row=1)
global hired_entry
hired_entry = Entry(main_frame)
hired_entry.grid(column=1, row=2)
global num_hired_entry
num_hired_entry = Entry(main_frame)
num_hired_entry.grid(column=1, row=3)
global delete_row_entry
delete_row_entry = Entry(main_frame)
delete_row_entry.grid(column=4, row=2)
def table_headers():
row_header = Label(main_frame, text='Row', font = 'Arial 10 bold')
row_header.grid(column=0, row=4)
customer_header = Label(main_frame, text='Customer Name', font = 'Arial 10 bold')
customer_header.grid(column=1, row=4)
receipt_header = Label(main_frame, text='Receipt Number', font = 'Arial 10 bold')
receipt_header.grid(column=3, row=4)
item_header = Label(main_frame, text='Item Hired', font = 'Arial 10 bold')
item_header.grid(column=2, row=4)
num_header = Label(main_frame, text='Number Hired', font = 'Arial 10 bold')
num_header.grid(column=4, row=4)
def append_entry():
global second_frame
second_frame = Frame(main_window)
second_frame.grid(column=0, row=6)
leader_error_var.set("")
location_error_var.set("")
numcamper_error_var.set("")
weather_error_var.set("")
global name_count
name_count = 0
global ROWS_ABOVE
ROWS_ABOVE = 6
try:
name_entry_str = str(name_entry.get())
hired_entry_str = str(hired_entry.get())
receipt_entry_int = str(receipt_entry.get())
num_hired_entry_int = str(num_hired_entry.get())
if len(name_entry.get()) != 0:
input_data_col1.append([name_entry_str])
input_data_col2.append([hired_entry_str])
input_data_col3.append([receipt_entry_int])
input_data_col4.append([num_hired_entry_int])
counters['total_entries'] += 1
print(input_data_col1)
print(input_data_col2)
print(input_data_col3)
print(input_data_col4)
while name_count < counters ['total_entries']:
global name
name = Label(second_frame, text=(input_data_col1[name_count][-1])) ##using -1 selects the latest entry in the list
name.grid(column=1, row=name_count + ROWS_ABOVE, padx=50)
item = Label(second_frame, text=(input_data_col2[name_count][-1]))
item.grid(column=2, row=name_count + ROWS_ABOVE, padx=50)
row = Label(second_frame, text=name_count)
row.grid(column=0, row=name_count + ROWS_ABOVE, padx=60)
receipt = Label(second_frame, text=(input_data_col3[name_count][-1]))
receipt.grid(column=3, row=name_count + ROWS_ABOVE, padx=50)
num = Label(second_frame, text=(input_data_col4[name_count][-1]))
num.grid(column=4, row= name_count + ROWS_ABOVE, padx=50)
name_count += 1
name_entry.delete(0,END)
receipt_entry.delete(0,END)
hired_entry.delete(0,END)
num_hired_entry.delete(0,END)
except:
leader_error_var.set("Check inputs")
#location_error_var.set("please enter a valid num")
#numcamper_error_var.set("numcamper error test")
weather_error_var.set("")
name_entry.delete(0,END)
receipt_entry.delete(0,END)
hired_entry.delete(0,END)
num_hired_entry.delete(0,END)
def delete_row():
user_del =int(delete_row_entry.get())
counters['total_entries'] -= 1
input_data_col1.pop(user_del)
input_data_col2.pop(user_del)
input_data_col3.pop(user_del)
input_data_col4.pop(user_del)
data = [input_data_col1,input_data_col2,input_data_col3,input_data_col4]
for widget in second_frame.winfo_children():
widget.destroy()
append_entry()
print(input_data_col1)
print(input_data_col2)
print(input_data_col3)
print(input_data_col4)
def error_prevention():
#leader_error_var.set("leader error test")
#location_error_var.set("location error test")
#numcamper_error_var.set("numcamper error test")
#weather_error_var.set("weather error test")
#weather_error_var.set("_______________")
leader_error = Label(main_frame, textvariable = leader_error_var, fg = 'red')
leader_error.grid(column=2, row=0)
location_error = Label(main_frame, textvariable = location_error_var, fg = 'red')
location_error.grid(column=2, row=1)
numcamper_error = Label(main_frame, textvariable = numcamper_error_var, fg = 'red', width = 13)
numcamper_error.grid(column=2, row=2)
weather_error = Label(main_frame, textvariable = weather_error_var, fg = 'red')
weather_error.grid(column=2, row=3)
def main():
global main_window
main_window = Tk()
global input_data_col1
input_data_col1 = []
global input_data_col2
input_data_col2 = []
global input_data_col3
input_data_col3 = []
global input_data_col4
input_data_col4 = []
global input_data
input_data = []
global main_frame
main_frame = Frame(main_window)
main_frame.grid(row=0,column=0)
global counters
counters = {'total_entries':0, 'name_count':0}
#global number
#number = {'total_entries':0}
def stringvars():
global location_error_var
location_error_var = StringVar()
location_error_var.set("")
global numcamper_error_var
numcamper_error_var = StringVar()
numcamper_error_var.set("")
global leader_error_var
leader_error_var = StringVar()
leader_error_var.set("")
global weather_error_var
weather_error_var = StringVar()
leader_error_var.set("")
stringvars()
entry_labels()
entry()
error_prevention()
button()
table_headers()
main()
main_window.mainloop()
Under the code
for widget in second_frame.winfo_children():
widget.destroy()
add this block of code
second_frame.pack()
it will be like this
for widget in second_frame.winfo_children():
widget.destroy()
second_frame.pack()
I hope this helps you
You can use
main_window.geometry("1200x800+100+100")
to change size and position of main_window. Here the window width will be 1200 and height will be 800, positioned 100px to the top left corner of screen. The +100+100 is optional.
You may add geometry() to delete_row callback to resize the frame. Though you might have to calculate the proper size after widget deletion.
As to "when I delete a row, the rows that weren't deleted start to get smaller and compress",
That's due to how grid layout works. If there are two widgets on the same grid row, the grid height will be equal the the higher widget height. When the higher widget is removed, the grid will resize to the smaller widget height and appear to 'shrink'.
To solve that, you can try add padding to the widget, the syntax is
widget.grid(column=1,row=1,padx=(10,10),pady=(10,10))
Alternatively, you may try other layout management: .place will give you absolute layout control. Or you can use pack and let tkinter decide the proper position.

GPIO Interface, object not callable

from tkinter import *
from tkinter import font
root = Tk()
root.title("Wills Gui")
root.geometry('1400x700')
#root.configure(background='black')
def P1C():
if B1(fg) :
B1.fg(fg = red)
B1["text"] = "Pin 2 Active"
B1["fg"] = "green"
else:
B1.fg(fg = green)
B1["text"] = "Pin 2 Inactive"
B1["fg"] = "red"
B1 = Button(root, height = 8, width = 15, font="Times 12 bold",
wraplength=80, command = P1C, text="| Q | B1 Inactive", bg="black",
fg="yellow").grid(row =0,column =0)
root.mainloop()
I have simplified the code i just need it to change the colour of the button text from green to red, etc every time it is pressed.
The error is right there in the trace
in P1C if B1(fg) : NameError: name 'fg' is not defined
The variable fg in the function is not defined prior to use.

Tkinter PIL image not displaying inside of a function

I am using Tkinter to display images in a Toplevel() but when I put it inside of a function it doesn't work(This is very beginner I know)
# -*- coding: utf-8 -*-
import Tkinter
from Tkinter import *
import tkMessageBox
from tkMessageBox import *
import Image, ImageTk
import PIL.Image, PIL.ImageTk
import os
import subprocess
root = Tk()
root.title("Test")
quin=Toplevel()
C = Tkinter.Canvas(quin, bg="white", height = 350, width = 350)
directory=os.path.dirname(os.path.abspath(__file__))
filename=os.path.join(directory, 'un.png')
img=PIL.Image.open(filename)
tkimg=PIL.ImageTk.PhotoImage(img)
image = C.create_image(175,175,image=tkimg)
C.grid(row=5,column=5)
def Head():
h1 = Label(root, text = "How to Secure a Computer", fg ="white", bg = "#00b8ff", width = 6,bd=2, height =2, font = "Arial", relief = RAISED)
h1.grid(row= 0, column = 0, ipadx=122, pady=3, padx=5,columnspan=3)
def Mainmenu():
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=root.destroy)
menubar.add_cascade(label="Options", menu=filemenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_radiobutton(label="Help")
helpmenu.add_radiobutton(label="User Manual Security Configuration Guide")
menubar.add_cascade(label="Help", menu=helpmenu)
root.config(menu=menubar)
def Mainbuttons():
B1=Button(root,text="Services",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff",command=Services)
B2=Button(root,text="Account Policies",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B3=Button(root,text="Firewall Config",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B4=Button(root,text="User Logon Time",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B5=Button(root,text="Security Policies",height=2, width=6,bd=2, font = "Arial", fg = "#FFFFFF", bg = "#156cff")
B1.grid(row = 1, column = 0, ipadx=120,pady=2,padx=5)
B2.grid(row = 1, column = 1, ipadx=120,pady=2,padx=5)
B3.grid(row = 2, column = 1, ipadx=120,pady=2,padx=5)
B4.grid(row = 2, column = 0, ipadx=120,pady=2,padx=5)
B5.grid(row = 3, column = 0, ipadx=120,pady=2,padx=5)
def Services():
serv=Toplevel()
servcanv=Canvas(serv,height=250, width=250)
servtext=Text(serv,width=26)
servtext.insert(INSERT, "To start go to your start menu, in the search bar\ntype services.msc")
servtext.grid(row=0, column=0)
servcanv.grid(row=0, column=1)
s = Tkinter.Canvas(serv, bg="white", height = 350, width = 350)
directory=os.path.dirname(os.path.abspath(__file__))
filename=os.path.join(directory, 'un.png')
img=PIL.Image.open(filename)
tkimg=PIL.ImageTk.PhotoImage(img)
image=s.create_image(175,175,image=tkimg)
s.grid(row=5,column=5)
Mainmenu()
Mainbuttons()
Head()
root.mainloop()
As you can see the code used to display the image is used twice, once inside a function and once outside. When outside it works perfectly, but when inside it doesn't work, it says the variable image is assigned but never used.
It does not work inside function, since tkimg is garbage collected after function finishes. You need to bind your images into variables that wont be garbage collected. For example to global variables, or instance variables in a class, rather than local variables.
To make tkimg be able to write to the global tkimg use global tkimg in the function.

Categories