0

I'm using tkinter and I am trying to compare a string [in this case, the original file] to text in a text widget. Here's the function and where I call the function:

def checkText():
    if(text.get("1.0", "end-1c") != currentText):
        print("Changed")

    root.after(1000, checkText())

and where I call:

root.after(1000, checkText()) #after 1 second, check text to see if it has changed

It returns the error:

  File "main.py", line 65, in checkText
  if(text.get("1.0", "end-1c") != currentText):
  RuntimeError: maximum recursion depth exceeded

Except with hundreds of 'File "main.py", line 65, in checkText'

Probably something obvious I'm overlooking, but help is appreciated.

Those are the only places the function is used or referenced to in the program, but just incase, here is where currentText is defined:

myfile = tkFileDialog.askopenfile(title='Open a file', mode='r')
    text.delete('1.0', END)
    loadedfile = myfile.read()
    currentText = myfile.read()

loadedFile is put directly into the text widget and works fine, so I assume currentText should be the same as loadedFile/text in the widget.

Thanks.

edit: formatting, also I realized I can just say currentText = loadedFile to simplify it, but I am keeping the original code in the question

edit: Entire function for getting text

def fileOpen(textView):
try:
    myfile = tkFileDialog.askopenfile(title='Open a file', mode='r')
    text.delete('1.0', END)
    loadedfile = myfile.read()
    currentText = loadedFile
    currentFile = myfile.name
    currentName = currentFile
    currentName = currentName.rsplit('/', 1)[-1] #get the 'name.ext' part only
    currentName = currentName.rsplit('\\', 1)[-1] #incase you're using windows
    currentFileButton.config(text = currentName)
    myfile.close()
    textView.insert("end", loadedfile)
except:
    return

def saveAs(): #define how to save files
try:
    global text
    t = text.get("1.0", "end-1c")
    saveLocation = tkFileDialog.asksaveasfilename()
    file1 = open(saveLocation, "w+")
    file1.write(t)
    file1.close()
except:
    return

later:

text = Text(textFrame, bd=0, bg=color, fg=textColor) #make text editor box
Right leg
  • 16,080
  • 7
  • 48
  • 81

1 Answers1

0

I finally got it. As you said, it's obvious, but actually not so obvious.

The problem lies in your call to after.

When calling after, you need to pass a time, and a callback, which is the function that will be called after the given time. Note that what must be passed is a function.

But when you call root.after(1000, checkText()), the second argument is not a function. It's a value, that corresponds to the return value of the checkText function.


What happens when you pass checkText() to after:

  1. checkText is called with no arguments
  2. The returned value is passed to after

But when you call checkText, a new call to root.after(1000, checkText()) is reached, and checkText() must be evaluated, so checkText is called.

Every call is immediate (ie, it does not occur after 1000ms), because the checkText() expression needs to be evaluated in order to be passed to after.


As I said, the second argument for the after method is a function. Therefore, the right call is root.after(1000, checkText).

The full code:

def checkText():
    if(text.get("1.0", "end-1c") != currentText):
        print("Changed")

    root.after(1000, checkText)

root.after(1000, checkText)

This will effectively schedule the checkText function to be called 1000ms later.

Right leg
  • 16,080
  • 7
  • 48
  • 81