Обнаружение, когда TextBox был отредактирован, а не обнаружение нажатия клавиши?
У меня есть программа для заметок, которая позволяет мне переключаться между заметками одним нажатием кнопки. Это удобно для меня. У меня есть небольшая безопасность, в которой, когда у меня есть активные заметки в текстовом поле, нажмите любую клавишу на моей клавиатуре, находясь внутри этого текстового поля, а затем попытался выбрать другую группу заметок, она спросит меня, хочу ли я менять заметки без экономии.
Это работает достаточно хорошо, но мне нужно найти способ, в котором он обнаруживает, только если изменения сделаны для заметок, а не для обнаружения нажатия клавиши. Причина этого заключается в том, что я не могу использовать "CTRL-C"
для копирования разделов моих заметок, не приводя в движение события, вызывающие всплывающее предупреждение. Я хотел бы иметь возможность продолжить прыжок из одной группы заметок в другую, если не было сделано редактирование текста внутри TextBox.
Если вы попытаетесь скопировать любой текст, который вы выделите с помощью "CTRL-C"
вы увидите, что попытка переключить заметки также спросит вас, хотите ли вы переключиться. Я пытаюсь избежать этого, и я полагаю, что должен быть способ проверить, были ли заметки какие-либо изменения, а не обнаружение keypress
TextBox.
Я попытался использовать textvariable
с track
но текстовое поле tkinters, похоже, не может использовать эту опцию.
Ниже приведен простой пример того, как вводить текст в текстовое поле, а затем выбирать для открытия другого набора заметок спросит вас, хотите ли вы продолжить.
from tkinter import *
from tkinter import messagebox
class MiniApp(Frame):
def __init__(self, master, *args, **kwargs):
Frame.__init__(self, master, *args, **kwargs)
self.master = master
self.text_is_edited = False
self.add_text = Button(self.master, text = "Add text to TextBox", command = self.add_to_text)
self.add_text.grid(row = 0, column = 0, sticky = "we")
self.add_text = Button(self.master, text = "Add text to TextBox", command = self.add_to_text_2)
self.add_text.grid(row = 0, column = 1, sticky = "we")
self.text = Text(self.master, width = 35, height = 3)
self.text.grid(row = 1, column = 0, columnspan = 2, sticky = "nsew")
self.text.bind('<Key>', self.is_text_edited)
def add_to_text(self):
if self.text_is_edited == False:
self.text.delete(1.0, "end-1c")
self.text.insert("end-1c", "Some other text to work with.\nMore text.")
self.text.see("end-1c")
else:
answer = messagebox.askquestion("Update TextBox",
"Are you sure you want change the content of the TextBox? Any unsaved changed will be lost!")
if answer == "yes":
self.text.delete(1.0, "end-1c")
self.text.insert("end-1c", "Some other text to work with.\nMore text.")
self.text.see("end-1c")
self.text_is_edited = False
def add_to_text_2(self):
if self.text_is_edited == False:
self.text.delete(1.0, "end-1c")
self.text.insert("end-1c", "Text to test with.\nMore text.")
self.text.see("end-1c")
else:
answer = messagebox.askquestion("Update TextBox",
"Are you sure you want change the content of the TextBox? Any unsaved changed will be lost!")
if answer == "yes":
self.text.delete(1.0, "end-1c")
self.text.insert("end-1c", "Text to test with.\nMore text.")
self.text.see("end-1c")
self.text_is_edited = False
def is_text_edited(self, *args):
if self.text_is_edited == False:
self.text_is_edited = True
if __name__ == "__main__":
root = Tk()
app = MiniApp(root)
root.mainloop()
Вы ищете событие <<Modified>>
.
Однако вам не нужно беспокоиться об этом, потому что виджет "Текст" сохраняет сам измененный флаг. Вот пример (со многими другими предложениями кода тоже):
# wildcard imports are bad and lead to bugs. Use proper imports.
import tkinter as tk
from tkinter import messagebox
TEXT1 = "Some other text to work with.\nMore text."
TEXT2 = "Text to test with.\nMore text."
class MiniApp(tk.Frame):
def __init__(self, master, **kwargs): # there will never be any positional arguments, you don't need *args
tk.Frame.__init__(self, master, **kwargs)
# self.master = master # this line is built into tkinter widgets; you don't need to repeat it
# all widgets should use the Frame as master, not the root window
self.add_text = tk.Button(self, text = "Add text to TextBox", command = lambda: self.add_to_text(TEXT1))
self.add_text.grid(row = 0, column = 0, sticky = "we")
self.add_text = tk.Button(self, text = "Add text to TextBox", command = lambda: self.add_to_text(TEXT2))
self.add_text.grid(row = 0, column = 1, sticky = "we")
self.text = tk.Text(self, width = 35, height = 3)
self.text.grid(row = 1, column = 0, columnspan = 2, sticky = "nsew")
def add_to_text(self, text):
# don't copy / paste code. Use the computer to do repetitive things for you.
if self.text.edit_modified() and not messagebox.askyesno("Update TextBox",
"Are you sure you want change the content of the TextBox? Any unsaved changed will be lost!"):
return # abort!!
self.text.delete(1.0, tk.END) # this is a modification and will set the modified flag
self.text.insert(1.0, text)
self.text.see(tk.END)
self.text.edit_modified(False) # reset the modified flag to False
if __name__ == "__main__":
root = tk.Tk()
app = MiniApp(root)
app.pack()
root.mainloop()
Edit: Dammit Bryan избил меня снова.
Текстовый виджет отслеживает, был ли он изменен или нет. Вы можете запросить состояние в любое время, вызвав метод edit_modified
. Он вернет True или False. Вы можете использовать тот же метод, чтобы сбросить флаг, когда захотите - как правило, после того, как вы вставили текст через код.
Каждый раз, когда виджет будет изменен, этот флаг будет установлен в true. Поэтому, когда вы программно вставляете текст, вам нужно сбросить этот флаг до False.
Например:
def add_to_text(self):
# ask the widget if it has been modified
if self.text.edit_modified():
answer = messagebox.askquestion("Update TextBox",
"Are you sure you want change the content of the TextBox? Any unsaved changed will be lost!")
if answer != "yes":
return
self.text.delete(1.0, "end-1c")
self.text.insert("end-1c", "Some other text to work with.\nMore text.")
self.text.see("end-1c")
# reset the flag to false. If the user modifies the widget the flag
# will become True again
self.text.edit_modified(False)