Python and tkinter: NameError: global name 'roomChange' is not defined - python

I'm receiving the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python33\lib\tkinter\__init__.py", line 1475, in __call__
return self.func(*args)
File "D:\COMPUTER SCIENCE\Seating Plan\SeatingPlan TEST.py", line 205, in displayText
if roomChange.get().strip() == "":
NameError: global name 'roomChange' is not defined
When attempting to run the following code:
from tkinter import *
import tkinter.messagebox
def displayText():
""" Display the Entry text value. """
global roomChange
if roomChange.get().strip() == "":
tkinter.messagebox.showerror("Invalid Value", "Please enter a valid classroom name.")
else:
tkinter.messagebox.showinfo("Temporary Window", "Text value = " + roomChange.get().strip())
def roomChanger():
chrm = Tk()
chrm.title("Change Room")
chrm.wm_iconbitmap('./Includes/icon.ico')
chrm["padx"] = 40
chrm["pady"] = 20
# Create a text frame to hold the text Label and the Entry widget
textFrame = Frame(chrm)
#Create a Label in textFrame
roomChangeLabel = Label(textFrame)
roomChangeLabel["text"] = "Enter name of classroom: "
roomChangeLabel.pack(side=LEFT)
# Create an Entry Widget in textFrame
roomChange = Entry(textFrame)
roomChange["width"] = 50
roomChange.pack(side=LEFT)
textFrame.pack()
roomChangeButton = Button(chrm, text="Submit", command=displayText)
roomChangeButton.pack()
chrm.mainloop()
testButton = Button(window, text='Change Room', command=roomChanger)
testButton.place(x = 825, y = 360)
Can anyone suggest a solution to my problem?
Thanks

In roomChanger() you assign to roomChange:
roomChange = Entry(textFrame)
so you need to mark that name as a global inside that function too. Add a global roomChange statement in that function.
displayText() on the other hand, never tries to assign to roomChange and the global statement in that function can safely be removed.

I had the same problem.
Here was my solution:
from tkinter import *
from tkinter import messagebox
Some sort of namespace glitch. That second line shouldn't be necessary. Technically from a syntax perspective import * implies import messagebox too because it's part of it all.
Use those two lines, take away import tkinter.messagebox

Related

Function calling is not working in optionmenu widget in python [duplicate]

This question already has answers here:
"TypeError: method() takes 1 positional argument but 2 were given" but I only passed one
(10 answers)
Closed last year.
# Import module
from tkinter import *
import csv
import pandas as pd
# Create object
root = Tk()
def find_account_no():
with open('PartyNames.csv', newline ='') as f:
reader=csv.reader(f)
parties = []
parties.extend(reader)
global account_number_var
for i in parties:
if(i[0] == party_name_var):
account_number_var = i[1]
print(account_number_var)
else:
continue
return(account_number_var)
# Adjust size
root.geometry( "1361x768" )
root.state('zoomed')
with open('PartyNames.csv', newline ='') as f:
reader=csv.reader(f)
party_names = []
party_names.extend(reader)
global party_name_var
party_name_var = StringVar()
party_name_var.set("Select Party Name")
Label(root, text='Party Name').grid(row=0,column=0)
party_name_list = [" ".join(row) for row in party_names]
party_name = OptionMenu(root, party_name_var,*party_name_list,command=find_account_no)
party_name.grid(row=0,column=1)
Label(root, text='Account Number').grid(row=1,column=0)
global account_number
account_number = Entry(root)
account_number.grid(row=1, column=1)
# Execute tkinter
root.mainloop()
This is the code.On line 33 I am calling the function find_account_nobut it is throwing this error.
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\DELL\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "C:\Users\DELL\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 3943, in __call__
self.__callback(self.__value, *args)
TypeError: find_account_no() takes 0 positional arguments but 1 was given
Why?
I think, its because when a function is binded to something in tkinter, the function is always called with a argument being passed to it...
One way to eradicate is to define the function with a dummy argument like this...
# Import module
from tkinter import *
import csv
import pandas as pd
# Create object
root = Tk()
def find_account_no(event): # <-- 'event' is a dummy argument which plays no role in the function
with open('PartyNames.csv', newline ='') as f:
reader=csv.reader(f)
parties = []
parties.extend(reader)
global account_number_var
for i in parties:
if(i[0] == party_name_var):
account_number_var = i[1]
print(account_number_var)
else:
continue
return(account_number_var)
# Adjust size
root.geometry( "1361x768" )
root.state('zoomed')
with open('PartyNames.csv', newline ='') as f:
reader=csv.reader(f)
party_names = []
party_names.extend(reader)
global party_name_var
party_name_var = StringVar()
party_name_var.set("Select Party Name")
Label(root, text='Party Name').grid(row=0,column=0)
party_name_list = [" ".join(row) for row in party_names]
party_name = OptionMenu(root, party_name_var,*party_name_list,command=find_account_no)
party_name.grid(row=0,column=1)
Label(root, text='Account Number').grid(row=1,column=0)
global account_number
account_number = Entry(root)
account_number.grid(row=1, column=1)
# Execute tkinter
root.mainloop()

"can only concatenate str (not "int") to str" when zipping list of strings and list of objects

I get this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Hunter\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "c:\Users\Hunter\Documents\Programming\Python Scripts\Scripts\spoolClient\menuScript.py", line 46, in <lambda>
updateJsonButton = Button(preferences, text="Save Preferences", command=lambda: updateJson())
File "c:\Users\Hunter\Documents\Programming\Python Scripts\Scripts\spoolClient\menuScript.py", line 17, in updateJson
for i, j in zip(entryNames, entry):
File "C:\Users\Hunter\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1643, in cget
return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str
When trying to run my script:
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
from tkinter import filedialog
import qrMaker
import qrReader
import json
settings = {}
#define vars
preferencesSkippedRows = [1, 3, 5, 7, 9, 11]
def openPreferences():
def updateJson():
print("here")
for i, j in zip(entryNames, entry):
print("loopdie")
value = str(j.get())
settings[i]=value
settingsjson = json.dumps(settings)
print(settingsjson)
f = open("preferences.json","w")
f.write(settingsjson)
f.close()
preferences = Tk()
preferences.title("Preferences")
preferences.iconbitmap(qrMaker.getCurrentPath()+'icon.ico')
preferences.geometry('400x600')
topText = Label(preferences, width=30, text="Filament Spool Client Preferences")
cameraText = Label(preferences, width=30, text="Select Camera Instance:")
cameraEntry = Combobox(preferences, width=30, values=qrReader.getCameras())
qrWidthText = Label(preferences, width=30, text="QR Output Width (in.)")
qrWidthEntry = Entry(preferences, width=30)
qrHeightText = Label(preferences, width=30, text="QR Output Height (in.)")
qrHeightEntry = Entry(preferences, width=30)
text = [cameraText, qrWidthText, qrHeightText]
entry = [cameraEntry, qrWidthEntry, qrHeightEntry]
entryNames = ['cameraEntry', 'qrWidthEntry', 'qrHeightEntry']
updateJsonButton = Button(preferences, text="Save Preferences", command=lambda: updateJson())
for i in preferencesSkippedRows:
preferences.grid_rowconfigure(i, minsize=10)
topText.grid(column = 0, row = 0)
row=2
for text, entry in zip(text, entry):
text.grid(column = 0, row = row)
entry.grid(column = 1, row = row)
row+=2
updateJsonButton.grid(column=1, row=row+2)
preferences.mainloop()
openPreferences() #I call script.openPreferences() in my main program but I left this here for debugging purposes
I can see from the error message that the error occurs somewhere in the line that my zip function occurs, but I have no idea what causes this. Oddly enough, this error goes away if instead of setting updateJson equal to the command value of my Tkinter button state, I set updateJson, which calls the function right as the button object is initialized. I also know what the error is saying, I just don't know where an integer is coming from, and how I can fix this issue. Any help would be appreciated.
Update: I've just found that the actual zipping of the two lists is not the problem, but when I introduce the for loop, the same error occurs.
Answering to close out this thread, answer from "user2357112 supports Monica".
The issue in this script is that for text, entry in zip(text, entry) literally uses "entry" in the for loop, and is executed after the button instance is created, meaning that if updateJson is called during the button object initialization, then there will be no error thrown as entry is still defined as a list. However, after for text, entry in zip(text, entry) executes at startup, entry is now defined as the last object in the list entry, no longer the list entry itself. When the user presses the button and updateJson is called, an error is thrown as entry is not a list anymore(I'm not 100% sure on the error part).

How to pass a entry field value to a function

I am trying to make a GUI based encryption program using tkinter on python3. Here one option is to encrypt an Image now there is an entry field where the user will enter the mode, 1 for RGB and 0 for greyscale. Now I am trying to pass that entry field value to the encrypt and decrypt function which will execute upon pressing the corresponding button. But I am getting an error while I am passing the value to the function. The script where the buttons and the entry field is written, as follows:
global mode
def getvalue():
mode =int(mode_txt.get())
return mode
image_window = Tk()
image_window.geometry ( '350x200' )
image_window.title ('Image Cryptography')
lbl1 = Label(image_window, text = "Select mode(0 for greyscale/ 1 for RGB): " ).place( x=20, y=40 )
mode_txt = IntVar
mode_txt = Entry(image_window, width = 4) #the entry field
mode_txt.place(x= 300, y=40)
mode_txt.bind('<Return>', getvalue)
mode_txt.pack()
Now I am passing the mode like this:
def encrypt():
mode = getvalue()
if(mode == 0): #greyscale
#some code#
The buttons are like this:
btn_decrypt = Button( image_window, text = "Image Decryption", command = decrypt)
btn_decrypt.place( x=20, y=100 )
btn_encrypt = Button( image_window, text = "Image Encryption", command = encrypt)
btn_encrypt.place( x=200, y=100 )
btn_exit = Button( image_window, text = "Go Back" , command = goback).place( x=140, y=150 )
image_window.mainloop()
The error I am getting is:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib64/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "image1.py", line 98, in decrypt
if(mode == 0):
NameError: name 'mode' is not defined
I don't know where I'm am going wrong? Any help will be appreciated. Thank you.

Using the lambda function in 'command = ' from Tkinter.

This is a very easy code to understand things :
Main :
import pdb
#pdb.set_trace()
import sys
import csv
sys.version_info
if sys.version_info[0] < 3:
from Tkinter import *
else:
from tkinter import *
from Untitled import *
main_window =Tk()
main_window.title("Welcome")
label = Label(main_window, text="Enter your current weight")
label.pack()
Current_Weight=StringVar()
Current_Weight.set("0.0")
entree1 = Entry(main_window,textvariable=Current_Weight,width=30)
entree1.pack()
bouton1 = Button(main_window, text="Enter", command= lambda evt,Current_Weight,entree1: get(evt,Current_Weight,entree1))
bouton1.pack()
and in another file Untitled i have the "get" function :
def get (event,loot, entree):
loot=float(entree.get())
print(loot)
When i run the main i receive the following error :
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/idlelib/run.py", line 121, in main
seq, request = rpc.request_queue.get(block=True, timeout=0.05)
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/queue.py", line 175, in get
raise Empty
queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/tkinter/init.py", line 1533, in call
return self.func(*args)
TypeError: () missing 3 required positional arguments: 'evt', 'Current_Weight', and 'entree1'
How can i solve that ?
I thought the lambda function allows us to uses some args in a event-dependant function.
The command lambda does not take any arguments at all; furthermore there is no evt that you can catch. A lambda can refer to variables outside it; this is called a closure. Thus your button code should be:
bouton1 = Button(main_window, text="Enter",
command = lambda: get(Current_Weight, entree1))
And your get should say:
def get(loot, entree):
loot = float(entree.get())
print(loot)
Actually, you just need the Entry object entree1 as the lamda pass-in argument. Either statement below would work.
bouton1 = Button(main_window, text="Enter", command=lambda x = entree1: get(x))
bouton1 = Button(main_window, text="Enter", command=lambda : get(entree1))
with the function get defined as
def get(entree):
print(float(entree.get()))

Class Variable Retrieval in Python

This is a GUI I’ve been writing for a script I already have working. What I’m struggling with here is retrieving the information in the textboxes.
Under the definition generate I am able to pop a name off of listx but I am unable to grab the local variable entry from any of the instances of the new_title_box class.
from Tkinter import *
import ttk
boxvar=""
folder=""
listx=[]
count = 1
myrow = 1
class new_title_box:
def __init__(self,name):
global myrow, count, listx
self.entry = StringVar()
self.name = name
self.name = ttk.Entry(mainframe,width=45,textvariable=self.entry)
self.name.grid(column=1,row=myrow+1,sticky=(N,W))
listx.append(name)
print(listx) ## For debugging to insure that it is working correctly, if it gives output it, this part works
myrow = myrow + 1
count=count+1
def make_new(*args):
new_title_box('box'+str(count))
def generate(*args):
global listx, boxvar
while len(listx) > 0:
boxvar=listx.pop(0)
print(boxvar) ## For debugging to insure that it is working correctly, if it gives output it, this part works
folder = boxvar.entry.get() ## Not working here
print(folder) ## For debugging to insure that it is working correctly, if it gives output it, this part works
root = Tk()
root.title("File Maker")
mainframe = ttk.Frame(root, padding = "50 50 50 50")
mainframe.grid(column = 0,row = 0,sticky = (N, W, E, S))
mainframe.columnconfigure(0,weight=1)
mainframe.columnconfigure(0,weight=1)
add_entry = ttk.Button(mainframe,width=20, text = "add entry", command=make_new)
add_entry.grid(column=2,row=2,sticky=(N,W))
add_entry = ttk.Button(mainframe,width=20, text = "make files", command=generate)
add_entry.grid(column=2,row=3,sticky=(N,W))
root.mainloop()
Here's the traceback I'm getting:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python33\lib\tkinter_init_.py", line 1442, in call
return self.func(*args)
File "C:\python\SampAqTkinter.py", line 28, in generate
folder = boxvar.entry ## Not working here
AttributeError: 'str' object has no attribute 'entry'
There are two things that need to be changed to fix the problem you describe:
In the new_title_box.__init__() method change: listx.append(name) to listx.append(self.name)
In the generate() function, change: folder = boxvar.entry.get() to folder = boxvar.get().
You are appending a string to listx, use self.name instead of the local string name

Categories

Resources