I am trying to put together a GUI that would read from a continuously updated TXT file and updated every once in a while. So far I succeeded with the first part and I am failing to use 'root.after()' to loop the whole thing but it results in NameError:
import tkinter as tk
root = tk.Tk()
class App:
def __init__(self, root):
frame = tk.Frame(root)
frame.pack()
iAutoInEN = 0
iAvailableEN = 0
self.tkAutoInEN = tk.StringVar()
self.tkAutoInEN.set(iAutoInEN)
self.tbAutoInEN = tk.Label(root, textvariable=self.tkAutoInEN)
self.tbAutoInEN.pack(side=tk.LEFT)
self.button = tk.Button(frame, text="Start", fg="red",
command=self.get_text)
self.button.pack(side=tk.LEFT)
def get_text(self):
fText = open("report.txt") #open a text file in the same folder
sContents = fText.read() #read the contents
fText.close()
# omitted working code that parses the text to lines and lines
# to items and marks them with numbers based on which they are
# allocated to a variable
if iLineCounter == 1 and iItemCounter == 3:
iAutoInEN = int(sItem)
self.tkAutoInEN.set(iAutoInEN)
root.after(1000,root,get_text(self))
app = App(root)
root.mainloop()
try:
root.destroy() # optional; see description below
except:
pass
The first instance runs without any problems and updates the value from 0 to the number in the TXT file but is accompanied with an error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\...\Python35\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/.../pythonlab/GUI3.py", line 117, in get_text
self.after(1000,root,get_text())
NameError: name 'get_text' is not defined
EDIT:
When changed to the recommended "self.after(1000,self.get_text)"
class App:
...
def get_text(self):
fText = open("report.txt") #open a text file in the same folder
sContents = fText.read() #read the contents
fText.close()
# omitted code
if iLineCounter == 1 and iItemCounter == 3:
iAutoInEN = int(sItem)
self.tkAutoInEN.set(iAutoInEN)
self.after(1000,self.get_text)
Error changes
Traceback (most recent call last):
File "C:/.../pythonlab/GUI3.py", line 6, in <module>
class App:
File "C:/.../pythonlab/GUI3.py", line 117, in App
self.after(1000, self.get_text)
NameError: name 'self' is not defined
Also please consider this is my very first programme (not only) in Python, so I would appreciate if you are a little bit more explicit with your answers (e.g. when pointing out an indentation error, please refer to an exact line of code).
Because get_text is a method of App class you should call it as self.get_text.
After is a tkinter method. In that case you should call it as root.after. And self refers to the class you are in. So because get_text is a method of current class you should call is with self which is like this in other programming languages like Java.
...
root.after(1000, self.get_text)
...
Firstly, like James commented, you should fix your indentation so that the functions are a part of the class.
Then, change this line
root.after(1000,root,get_text(self))
to this
root.after(1000, self.get_text)
Check out the answer to the following question, which uses the code I just gave you:
Tkinter, executing functions over time
Related
I'm getting an UnboundLocalError
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\Ya Bish\Projects\Obracun Sati\main.py", line 249, in item_selected
app = EmpWindow(top,record)
UnboundLocalError: local variable 'record' referenced before assignment
when asking for filename and
def __init__(self,master):
self.master = master
self.openButton = Button(self.frame, text="Open",
command=self.openFile)
...
self.tree = Treeview(self.master, columns=self.columns, show="headings")
...
self.tree.bind('<<TreeviewSelect>>', self.item_selected)
def openFile(self):
...
self.tree.delete(*self.tree.get_children())
filename = filedialog.askopenfilename()
calc(filename)
for e in emps:
self.tree.insert('', END, values=e.treeValues)
while this Toplevel() window is either active or have been previously active.
def item_selected(self, event):
for selected_item in self.tree.selection():
item = self.tree.item(selected_item)
record = item['values'][0]
top = Toplevel()
app = EmpWindow(top,record)
top.mainloop()
EmpWindow is just a notebook class with two tabs defined and couple of labels so I don't think that code is necessary.
This may be an error with event and Bind but I don't understand that part at all so I don't even know how to approach it.
This might be happening because your for-loop in item_selected is not even getting a single iteration in which case record will never be defined. A simplified version of this is the following
def f():
for x in range(0):
print(x)
print(x)
f()
This gives the exact same error as your code. This kind of error occurs whenever you reference a variable before you assign it inside functions.
When I try to run my code I get an error saying that:
Traceback (most recent call last):
File "C:/Users/Vilho/PycharmProjects/BitlifeYritys1.0/main.py", line 37, in <module>
kill = Button(screen1, text="End game", bg="green", command=end_game("end game button was pressed"), height=4, width=11)
File "C:/Users/Vilho/PycharmProjects/BitlifeYritys1.0/main.py", line 9, in end_game
main_screen.destroy()
NameError: name 'main_screen' is not defined
I don't know what caused the error because I tried to put globals everywhere I could.
The rest of the code is here:
https://shrib.com/?v=nc#VioletCrestedTuraco4wYoed9
You don't define main_screen until you call main_game:
def main_game():
global main_screen
main_screen = Tk()
But you never call this function.
You do, however, call the end_game function. This means that you are calling the destroy method on an object that does not yet exist:
main_screen.destroy()
Conclusion: you either need make sure that main_game is called before end_game, or you need to create a blank window (which might not be the best idea).
I am playing around tkinter, and I was wondering if I had declared a method within an object, can I call it using the 'protocol' method of tkinter? or any function to be exact ie.
class Notepad():
...
...
def exit_func():
#Messagebox command warning 'You are exiting'
root = tk.Tk()
notepad = Notepad(root)
root.geometry("800x500")
root.mainloop()
#Problem is here
root.protocol("WM_DELETE_WINDOW", app.exit_func())
I tried this with my program, where my 'exit_func' had a 'get' function from tkinter and i got this error:
Traceback (most recent call last):
File "Notepad_with_console.py", line 204, in <module>
root.protocol("WM_DELETE_WINDOW", notepad.exit_file())
File "Notepad_with_console.py", line 175, in exit_file
if self.text.get(1.0,tk.END) != '' and self.current_file_dir == '':
File "C:\Anaconda\lib\tkinter\__init__.py", line 3246, in get
return self.tk.call(self._w, 'get', index1, index2)
_tkinter.TclError: invalid command name ".!text"
Is there a reason for this? Thanks!
root.protocol requires a reference to a function. Instead, you're immediately calling a function and then passing in the result.
Consider this code:
root.protocol("WM_DELETE_WINDOW", app.exit_func())
That code is functionally identical to this:
result = app.exit_func()
root.protocol("WM_DELETE_WINDOW", result)
Instead, you need to pass in a reference to the function:
root.protocol("WM_DELETE_WINDOW", app.exit_func)
I'm trying to write a GUI for my code. My plan is to use tkinter's StringVar, DoubleVar, etc. to monitor my input in real time. So I found out the DoubleVar.trace('w', callback) function. However, every time I make the change I get an exception:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Anaconda2\lib\lib-tk\Tkinter.py", line 1542, in __call__
return self.func(*args)
TypeError: 'NoneType' object is not callable
I have no idea what's going wrong. I'm using python 2.7
My code is as follows:
from Tkinter import *
class test(Frame):
def __init__(self,master):
Frame.__init__(self,master=None)
self.main_frame = Frame(master);
self.main_frame.pack()
self.testvar = DoubleVar()
self.slider_testvar = Scale(self.main_frame,variable = self.testvar,from_ = 0.2, to = 900, resolution = 0.1, orient=HORIZONTAL,length = 300)
self.slider_testvar.grid(row = 0, column = 0, columnspan = 5)
self.testvar.trace('w',self.testfun())
def testfun(self):
print(self.testvar.get())
root = Tk()
root.geometry("1024x768")
app = test(master = root)
root.mainloop()
Consider this line of code:
self.testvar.trace('w',self.testfun())
This is exactly the same as this:
result = self.testfun()
self.testvar.trace('w', result)
Since the function returns None, the trace is going to try to call None, and thus you get 'NoneType' object is not callable
The trace method requires a callable. That is, a reference to a function. You need to change that line to be the following (notice the missing () at the end):
self.testvar.trace('w',self.testfun)
Also, you need to modify testfun to take arguments that are automatically passed by the tracing mechanism. For more information see What are the arguments to Tkinter variable trace method callbacks?
This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 6 years ago.
I want to get an input data from user and put it into text file, but there's an error as follows:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\dasom\AppData\Local\Programs\Python\Python35-32\Lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/Users/dasom/PycharmProjects/Exercise/4.pyw", line 5, in save_data
filed.write("Depot:\n%s\n" % depot.get())
AttributeError: 'NoneType' object has no attribute 'get'`
It says about line 1549 in init.py file, I looked up for it and I coudn't understand what the problem is.
def __call__(self, *args):
"""Apply first function SUBST to arguments, than FUNC."""
try:
if self.subst:
args = self.subst(*args)
return self.func(*args)
except SystemExit:
raise
except:
self.widget._report_exception()
Here's my whole code
from tkinter import *
def save_data():
filed = open("deliveries.txt", "a")
filed.write("Depot:\n%s\n" % depot.get())
filed.write("Description :\n%s\n" % description.get())
filed.write("Address :\n%s\n" % address.get("1.0", END))
depot.delete(0, END)
description.delete(0, END)
address.delete("1.0", END)
app = Tk()
app.title('Head-Ex Deliveries')
Label(app, text='Depot:').pack()
depot = Entry(app).pack()
Label(app, text="Description:").pack()
description = Entry(app).pack()
Label(app, text='Address:').pack()
address = Text(app).pack()
Button(app, text='save', command=save_data).pack()
app.mainloop()
Actually, I just typed the code of textbook. Your help will be greatly appreciated. Thanks.
If the textbook has code like that, it's a poor textbook. This line:
depot = Entry(app).pack()
is doing two things. First it creates an Entry, and then it places it into the app. Unfortunately, the pack() method acts in-place and returns None instead of a reference to the original Entry widget. Split it up:
depot = Entry(app)
depot.pack()
Do this for all similar instances of assigning the None return value from an in-place method to a reference that you expect to point to a useful object.