I'm getting the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/Users/XXXXXXXXXXXXX/Desktop/Python/Test Py/TestGUI.py", line 37, in trans1
print(enter_principal)
NameError: name 'enter_principal' is not defined
I'm currently trying to learn python, so I'd be lying if I said I had any idea on what is going wrong. Here is my source code, trying to make a basic compound interest calculator. Getting this error when I'm trying to get an input from the user. Code:
#Importing GUI Module
import tkinter as tk
from tkinter import *
#Creating window
root = tk.Tk()
####Functions#####
#Root screen exit button
def exitroot():
root.destroy()
#principal input
def principal():
#Creating principal window and destroying home window
window = tk.Tk()
exitroot()
#Creating widgets
title_principal = tk.Label(window, text='Please enter your pricipal value: ')
enter_principal = tk.Entry(window)
b1 = tk.Button(window, text='Submit', command=trans1)
title_principal.grid()
enter_principal.grid()
b1.grid()
def trans1():
#temp function for testing purposes
print(enter_principal)
####
#CREATING HOME WINDOW WIDGETS
title_main = tk.Label(root, text="Compound Intrest Calculator", font=("Arial", 20, 'bold'))
start_button = tk.Button(root, text="Start", width='6', height='2', command=principal)
exit_button = tk.Button(root, text="Exit", width='6', height='2', command=exitroot)
credits_main = tk.Label(root, text="M.CXXXXXXXX 2020", font=("Arial", 8))
#PACKING HOME WINDOW WIDGETS VIA GRID
title_main.grid(row='0', columnspan='2')
start_button.grid(row='1', column='0')
exit_button.grid(row='1', column='1')
credits_main.grid(row='2', columnspan='2')
root.mainloop()
Any help is greatly appreciated! I apologise if my code is hard to follow or has blantant errors. I've spent some time looking for a fix but I am really struggling as none have worked.
You need to change
b1 = tk.Button(window, text='Submit', command=trans1)
TO:
b1 = tk.Button(window, text='Submit', command=lambda: trans1(enter_principal.get()))
The reason being is because you need to pass in the value typed into the tk.Entry by using enter_principal.get().
Lambda allows the function to be called only when the button is pressed.(since the command contains parenthesis and so would be called automatically)
Once you've passed this in, you can then pass it into the trans1 function and print it.
def trans1(answer):
# temp function for testing purposes
print(answer)
Related
I am trying to create a pop up window with Tkinter where I can enter values with an entry window to use them in the main code.
Currently I am trying to simply output the input. I can't get it to work, does anyone have an idea how I can solve this problem?
Here is a small snippet of my code. I have not used the variables from the functions anywhere else in the code.
root = Tk() # set up GUI
menuleiste = Menu(root) #menu bar
def take_over_Temp():
#Tempstring = str(eKnopf.get())
print(eKnopf.get())
print("got it")
def open_popup():
#global eKnopf
top= Toplevel(root)
top.geometry("750x250")
top.title("Child Window")
#Label(top, text= "Hello World!", font=('Mistral 18 bold')).place(x=150,y=80)
eKnopf = Entry(top, bd = 5).place(x=10,y=100, width=100)
button_take_Temp = Button(top, text='Set Temperature', fg="red", command=take_over_Temp)
button_take_Temp.place(x=10, y=150, width=100)
return(eKnopf)
optionen_menu.add_command(label="Offset", command = open_popup)
When I try it like this I get this Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.9/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
File "/home/user/FAC.py", line 724, in take_over_Temp
print(eKnopf.get())
NameError: name 'eKnopf' is not defined
You need to pass in eKnopf as a parameter to take_over_Temp()
eKnopf = Entry(top, bd = 5)
eKnopf.place(x=10, y=100, width=100)
button_take_Temp = Button(
top,
text='Set Temperature',
fg="red",
# use a lambda to pass `eKnopf` as an argument
command=lambda ent=eKnopf: take_over_Temp(ent)
)
Then modify take_over_Temp to accept and use that value:
def take_over_Temp(ent):
print(ent.get())
FYI, the error you're seeing is essentially saying that the function take_over_Temp doesn't know what eKnopf is because it doesn't exist within the scope of the function.
My goal was to refresh a label with its new contents on the click of a button, but when i click the button i get the error message below the code. I understand that it cant access the variable, but i dont understand why. How do i fix it and make the label update when i enter new text in the entry box and click the change button?
Main.py:
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter.messagebox import showinfo # Message Box
from functions import *
root = tk.Tk()
current_title = Label(root, text=homepage.get_title())
current_title.grid(row=1, column=0, sticky=E)
def refresh_title_label():
current_title.destroy()
current_title = Label(root, text=homepage.get_title()) # this homepage.get_title() gets the text from a html file
current_title.grid(row=1, column=1, sticky=W)
def change_title():
x = new_title_input.get()
homepage.change_title(x) # this changes the title in the html file
refresh_title_label()
showinfo('Title Changed')
new_title_label = Label(root, font='Helvetica 15', text='New Title: ' )
new_title_input = Entry(root, background='lightgrey', width=50 )
title_button = ttk.Button(root, text='Change', command=change_title)
new_title_label.grid(row=2, column=0, sticky=E)
new_title_input.grid(row=2, column=1, sticky=W)
title_button.grid(row=2, column=2, sticky=W)
if __name__ == "__main__":
root.mainloop()
functions.py:
# Importing the ssh connection
from ssh_config import *
# This is a class to change the index file
class homepage():
# Gets the website title
def get_title():
data = ssh_command('grep web_title index.html')
data = data[26:]
data = data[:-11]
return data
# changes website title
def change_title(new_title):
current_title = homepage.get_title()
ssh_command(f"sed -i 's/{current_title}/{new_title}/g' index.html")
This is the error message:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\josep\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "c:\Users\josep\Desktop\tkinter-ssh-backend\Untitled-1.py", line 20, in change_title
refresh_title_label()
File "c:\Users\josep\Desktop\tkinter-ssh-backend\Untitled-1.py", line 12, in refresh_title_label
current_title.destroy()
^^^^^^^^^^^^^
UnboundLocalError: cannot access local variable 'current_title' where it is not associated with a value
I tried making the variable global but that didnt work
root = tk.Tk()
global current_title
current_title = Label(root, text=homepage.get_title())
current_title.grid(row=1, column=0, sticky=E)
And i have tested to see if the ssh is working correctly and it is.
In main.py, you cannot put current_title.destroy() before current_title = Label(root). You do this after current_title.grip()
If you want to destroy Label(), you can't do simultaneous in the
refresh_title_label() function.
You can put current_title.destroy() in the change_title() function.
It is up to you to suit your need.
Add current_title.config in the refresh_title_label() function.
I am not using ssh_config. I can do workaround to show.
Snippet:
def refresh_title_label():
current_title.config(text=new_title_input.get())
current_title.grid(row=1, column=0, sticky=E)
def change_title():
x = new_title_input.get()
homepage.change_title(x) # this changes the title in the html file
refresh_title_label()
showinfo('Title Changed')
current_title.destroy()
current_title = Label(root, text=homepage.get_title())
Screenshot:
Screenshot after clicking Change button:
Screenshot destroy the Label:
I have a tkinter.Label created inside a function and from a totally seperate part of my code I need to update the text.
I have tried just about every solution google provides over the last hour and I can't get any of them to work, some error, some show blanks, some just fail to do anything.
I am creating the labels as follows
def createWindow():
window = tkinter.Tk()
container = tkinter.Frame(window, padx=5, pady=5)
summaryFrame = tkinter.Frame(container, bd=2, relief='groove')
summaryFrame.pack(side='top', fill='x')
summaryUser = tkinter.Label(summaryFrame, text='Some text').grid(row=1, column=1, sticky='w')
Much later I need to change the text of this label but because I'm no longer in this createWindow() function I don't have access to the summaryUser variable that contains the text.
I have tried summaryEvent["text"] (errors because it's not available), I have tried using a global variable and using textvariable=AGlobalVariable instead of text='Some text' (leaves the label text blank) and many other google results all with no success.
This seems like the sort of functionality that should be easier than this...
EDIT 1
I have tried the following...
summaryUserText = 'Some text'
def createWindow():
global summaryUserText
window = tkinter.Tk()
container = tkinter.Frame(window, padx=5, pady=5)
summaryFrame = tkinter.Frame(container, bd=2, relief='groove')
summaryFrame.pack(side='top', fill='x')
summaryUser = tkinter.Label(summaryFrame, textvariable=summaryUserText)
summaryUser.grid(row=1, column=1, sticky='w')
When I try this the label just starts blank, not with the content of the variable.
EDIT 2
I have also tried the following...
summaryUserText= tkinter.StringVar()
summaryUserText.set('Some text')
def createWindow():
...
summaryUser= tkinter.Label(summaryFrame, textvariable=summaryUserText)
But as soon as python sees the first line it errors with the following...
File "C:\Program Files\Python37\lib\tkinter\__init__.py", line 480, in __init__
Variable.__init__(self, master, value, name)
File "C:\Program Files\Python37\lib\tkinter\__init__.py", line 317, in __init__
self._root = master._root()
AttributeError: 'NoneType' object has no attribute '_root'
Edit 3
The simplest code that simulates the issue in one complete file
import tkinter
def loadEvent():
global summaryEventText
summaryEventText.set('Updated')
print('Updated')
def createWindow():
global summaryEventText
window = tkinter.Tk()
summaryEventText = tkinter.StringVar()
summaryEventText.set('Init')
summaryEventLabel = tkinter.Label(window, text='Event:').grid(row=0, column=0, sticky='e')
summaryEvent = tkinter.Label(window, textvariable=summaryEventText).grid(row=0, column=1, sticky='w')
window.mainloop()
createWindow()
loadEvent()
No errors, the print('Updated') works but the summaryEventText.set('Updated') does nothing.
The short answer is: to change an object you must have a reference to that object. That's not unique to tkinter, it's a fundamental aspect of programming. You're using local variables which by definition means you can't access the widgets outside of that function. The solution, then, is to not use local variables.
A proper solution requires you to save a reference that the other function can access, or provide a function that can return a reference. Have the function return a reference, use a global variable, or use a class variable.
The simplest solution for your specific example is to use a global variable. For example:
import tkinter
def loadEvent():
...
summaryEventLabel.configure(text='Updated')
...
def createWindow():
global summaryEventLabel
...
summaryEventLabel = tkinter.Label(window, text='Event:')
summaryEventLabel.grid(row=0, column=0, sticky='e')
...
createWindow()
loadEvent()
However, your specific example won't work because window.mainloop() will not return until the window is destroyed or you call its quit method. This means that createWindow won't return, so loadEvent will not be called.
If you were to structure your program to avoid this problem -- for example, calling loadEvent in response to a button click or some other event -- this solution would work.
Here's a working example that updates the label after 5 seconds:
import tkinter
def loadEvent():
summaryEventLabel.configure(text='Updated')
print('Updated')
def createWindow():
global summaryEventLabel
window = tkinter.Tk()
summaryEventText = tkinter.StringVar()
summaryEventText.set('Init')
summaryEventLabel = tkinter.Label(window, text='Event:')
summaryEventLabel.grid(row=0, column=0, sticky='e')
summaryEvent = tkinter.Label(window, textvariable=summaryEventText).grid(row=0, column=1, sticky='w')
window.after(5000, loadEvent)
window.mainloop()
createWindow()
I'm very new to the tkinter module and have little to no experience with it.
I want to make a program where I could run it and an entry box would display as well as a button.
What I want the program to do is, when I left click the button, the canvas would close, and I would be able to assign a variable to the entry I typed in and be able to pass that to other functions. So I'd have tkinter.Entry('Type in text'), then after that I would click the tkinter.Button('Click Me'), and once I click the button the canvas would close and then be able to assign the tkinter.Entry as a variable that I could pass through to other functions.
In my program I was able to just do regular python without the canvas and type in an input() and then return that to my other functions, but I'm completely lost on how to remove the input() from console and replace it with a UI canvas with tkinter. Sorry if this isn't making a lot of sense.
import tkinter
window = tkinter.Tk()
window.title("Code Violation")
def Canvas():
keyword = tkinter.Label(window, text="Enter Keyword").grid(row=0)
tester = tkinter.Button(window, text="Generate File").grid(columnspan=2)
tkinter.Entry(window).grid(row=0, column=1)
window.mainloop()
----Afterwards Error Codes
Traceback (most recent call last):
File "C:/Users/oalbz/PycharmProjects/Code_Violation/CodeViolation.py", line 98, in <module>
main()
File "C:/Users/oalbz/PycharmProjects/Code_Violation/CodeViolation.py", line 29, in main
keyword = Canvas()
File "C:/Users/oalbz/PycharmProjects/Code_Violation/CodeViolation.py", line 12, in Canvas
Var = tkinter.StringVar()
File "C:\Users\oalbz\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 480, in __init__
Variable.__init__(self, master, value, name)
File "C:\Users\oalbz\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 317, in __init__
self._root = master._root()
AttributeError: 'NoneType' object has no attribute '_root'
I want to be able to take the entry.get() that's insie the callback function and return it to my main and use that as a parameter in my vacancy function
here is the code for my main
def main():
#Canvas()
keyword = Canvas()
print(keyword)
initial_index = open('CodeViolationIndex.html','r')
table_dict = removeTags(initial_index,'tr','td')
site_final_html = open('test.html','w')
#keyword = input('Enter Keyword you would like to search:')
vacancy(table_dict,keyword)
This is what I have so far in my Canvas function you gave me
def Canvas():
Var = tkinter.StringVar()
tkinter.Label(window, text="Enter Keyword").grid(row=0)
entry = tkinter.Entry(window, text="Enter Keyword",textvariable = Var)
entry.grid(row=1)
def callback():
keyword = entry.get()
#print(keyword)
window.destroy()
return keyword
tester = tkinter.Button(window, text="Generate File",command=callback)
tester.grid(columnspan=2)
keyword = callback()
return keyword
Try this code:
import tkinter
window = tkinter.Tk()
window.title("Code Violation")
def Canvas():
Var = tkinter.StringVar() #Making a variable which will store data
tkinter.Label(window, text="Enter Keyword:").grid(row=0) #Making label, no need to store it in a variable
entry = tkinter.Entry(window, text="Enter Keyword", textvariable = Var) #making entry
entry.grid(row=1)
def callback(): #this function will be triggered on button press
print(entry.get()) #get() method will give the value of the entry
window.destroy() #It will destroy the tkinter window
tester = tkinter.Button(window, text="Generate File", command = callback)
tester.grid(columnspan=2)
Canvas()
window.mainloop()
Edit:
Here is the code updated according to your updates:
import tkinter
def Canvas():
global keyword
window = tkinter.Tk()
window.title("Code Violation")
Var = tkinter.StringVar()
tkinter.Label(window, text="Enter Keyword").grid(row=0)
entry = tkinter.Entry(window, text="Enter Keyword",textvariable = Var)
entry.grid(row=1)
def callback():
global keyword
keyword = entry.get()
window.destroy() #This also quits the mainloop so function will continue to return statement
tester = tkinter.Button(window, text="Generate File",command=callback)
# >>>> >>>> >>>> ^ We are assigning the function callback here
tester.grid(columnspan=2)
window.mainloop()
return keyword
def main():
#Canvas()
keyword = Canvas()
print(keyword)
#...
main()
I am making this small program, where the user can input the x and y axis of the screen where they wish to move the mouse to, and how many time they would like to click on that pixel.
My problem is when I try to put the variables into this function, the arguments apparently cannot be converted? The SetCurPos() is the problem, it will take SetCurPos(x,y), but I receive the error:
File "C:\Python27\Scripts\ManipulationTools.py", line 13, in click
SetCursorPos(x,y)
ArgumentError: argument 1: : Don't know how to convert parameter 1
My Code:
from Tkinter import *
import time
import ctypes
#from MoveCursor import click
class ManipulationTools():
##############FUNCTIONS###################################
def click(x,y, numclicks):
SetCursorPos = ctypes.windll.user32.SetCursorPos
mouse_event = ctypes.windll.user32.mouse_event
SetCursorPos(x,y)
E1.DELETE(0, END)
E2.DELETE(0, END)
E3.DELETE(0, END)
for i in xrange(numclicks):
mouse_event(2,0,0,0,0)
mouse_event(4,0,0,0,0)
#############END FUNCTIONS################################
root = Tk()
root.maxsize(width=400, height=400)
root.minsize(width=400, height=400)
root.config(bg="black")
L1 = Label(root,text="Enter the x and y value here:", fg="white", bg="black")
L1.place(x=20, y=20)
Lx = Label(root, text="X:",fg="white",bg="black")
Lx.place(x=170,y=20)
Ly = Label(root, text="Y:",fg="white",bg="black")
Ly.place(x=240,y=20)
Lnum = Label(root, text="Number of Times:",fg="white",bg="black")
Lnum.place(x=150, y=100)
E1 = Entry(root, width=5, bg="grey", )
E1.place(x=190,y=20)
E2 = Entry(root, width=5, bg="grey",)
E2.place(x=260,y=20)
E3 = Entry(root, width=5, bg="grey",)
E3.place(x=260,y=100)
a=IntVar(E1.get())
b=IntVar(E2.get())
c=IntVar(E3.get())
con = Button(root, command=click(a,b,c), text="Confirm", bg="white")
con.place(x=300,y=300)
root.mainloop()
My Traceback error when I click the button to confirm the numbers in the fields entered:
Traceback (most recent call last):
File "C:\Python27\Scripts\ManipulationTools.py", line 6, in
class ManipulationTools():
File "C:\Python27\Scripts\ManipulationTools.py", line 53, in ManipulationTools
con = Button(root, command=click(a,b,c), text="Confirm", bg="white")
File "C:\Python27\Scripts\ManipulationTools.py", line 13, in click
SetCursorPos(x,y)
ArgumentError: argument 1: : Don't know how to convert parameter 1
What you call ####functions#### are actually methods, and hence, the first argument they get is always the reference to the instance of their containing class, which commonly is named self. You can, however, name that parameter like you want to, which is what happened here:
class ManipulationTools():
def click(x,y, numclicks):
x is what elsewhere would be called self, not the first argument that you give when doing something like
tools = ManipulationTools()
tools.click(100,200,1) ## this should actually give you an error -- ManipulationTools.click gets called with 4 arguments (self, 100, 200, 1), but is only defined for 3 (self, y, numclicks)
The right thing to do is:
class ManipulationTools():
def click(self, x,y, numclicks):