0

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).

Eleshar
  • 493
  • 4
  • 17
  • 1
    Fix your indentation. The methods haven't been indented, so aren't part of the class. – James K Aug 19 '16 at 19:41
  • Thanks - which methods you are referring to exactly? This is basically my first Python program and I am learning as I go, so I am still quite lost...:) – Eleshar Aug 19 '16 at 20:32
  • The indentation issues were fixed by Terry when he edited it. Before, since your `init` and `get_text` functions weren't indented, they didn't belong to the App class. The App class was then useless. Make sure to change the code on your computer to match the edited code in your question to stave off any future problems. – Xetnus Aug 19 '16 at 20:45
  • Right - this might have been because I struggled to convert the code to something postable - it is actually much longer but at certain places quite repetitive, so the indent might have gone awry when I deleted these parts, otherwise it looks pretty much the same. – Eleshar Aug 19 '16 at 20:58
  • Updated my answer. – alpert Aug 19 '16 at 21:10
  • Alpert: hello there, mr. Solution! – Eleshar Aug 19 '16 at 21:12

2 Answers2

2

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)
...
alpert
  • 4,500
  • 1
  • 17
  • 27
0

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

Community
  • 1
  • 1
Xetnus
  • 353
  • 2
  • 4
  • 13
  • Thanks - I tried to change the code accordingly but the new error is: "AttributeError: 'App' object has no attribute 'after' ". Also as above - not sure where you see the indentation error. – Eleshar Aug 19 '16 at 20:38
  • Check my comment I added to your question. Make sure your version of the code matches the question's code exactly (except for the corrected line of code that I gave you), since the question was edited to fix the indentation issues. – Xetnus Aug 19 '16 at 20:47
  • You can always try this instead: `root.after(3000, self.get_text)` – Xetnus Aug 19 '16 at 21:11