0

I wanted to monitor when the text in a tkinter Text widget was modified so that a user could save any new data they had entered. Then on pressing 'Save' I wanted to reset this.

I bound the Text widget's <<Modified>> event to a function so that making any changes to the text would update the 'Save' button from 'disabled' to 'normal' state. After hitting the Save button I ran a function which reset the modified flag and disabled the Save button again until further changes were made.

But I found that it seemed to only fire the event once. Hitting Save didn't reset the button to a 'disabled' state, and editing the text didn't seem to affect the Save button's state either after the first time.

Below is a minimal example to show how the flag doesn't seem to be reset.

import tkinter as tk

root = tk.Tk()

def text_modified(event=None):
    status_label.config(text="Modified = True")

def reset():
    if not text_widget.edit_modified():
        return
    status_label.config(text="Modified = False")
    text_widget.edit_modified(False)

text_widget = tk.Text(root, width=30, height=5)
text_widget.pack()
text_widget.bind("<<Modified>>", text_modified)

status_label = tk.Label(root, text="Modified = False")
status_label.pack()

reset_btn = tk.Button(root, text="Reset", command=reset)
reset_btn.pack()

root.mainloop()
TylerH
  • 20,799
  • 66
  • 75
  • 101
TomBCodes
  • 71
  • 5
  • 1
    Does this answer your question? [Python tkinter text modified callback](https://stackoverflow.com/questions/40617515/python-tkinter-text-modified-callback) – Jack Griffin Mar 05 '23 at 14:01

1 Answers1

2

It turns out that binding the <<Modified>> event to a function means that the function will run not when the Text widget text is changed, but whenever the modified flag is changed - whether it changes to True or to False. So my Save button was saving the data, disabling itself, and resetting the modified flag to False, and this flag change fired the <<Modified>> event, which was bound to a function which enabled the Save button again.

Here's a minimal example which shows what's going on. We just need to adjust the function we've bound the <<Modified>> event to so that it deals with modified being False as well:

import tkinter as tk

root = tk.Tk()

def modified_flag_changed(event=None):
    if text_widget.edit_modified():
        status_label.config(text="Modified = True")
        print("Text modified")
    else:
        print("Modified flag changed to False")

def reset():
    if not text_widget.edit_modified():
        print("Doesn't need resetting")
        return
    status_label.config(text="Modified = False")
    text_widget.edit_modified(False)
    print('Reset')

text_widget = tk.Text(root, width=30, height=5)
text_widget.pack()
text_widget.bind("<<Modified>>", modified_flag_changed)

status_label = tk.Label(root, text="Modified = False")
status_label.pack()

reset_btn = tk.Button(root, text="Reset", command=reset)
reset_btn.pack()

root.mainloop()
TylerH
  • 20,799
  • 66
  • 75
  • 101
TomBCodes
  • 71
  • 5