Обнаружение, когда TextBox был отредактирован, а не обнаружение нажатия клавиши?

118
12

У меня есть программа для заметок, которая позволяет мне переключаться между заметками одним нажатием кнопки. Это удобно для меня. У меня есть небольшая безопасность, в которой, когда у меня есть активные заметки в текстовом поле, нажмите любую клавишу на моей клавиатуре, находясь внутри этого текстового поля, а затем попытался выбрать другую группу заметок, она спросит меня, хочу ли я менять заметки без экономии.

Это работает достаточно хорошо, но мне нужно найти способ, в котором он обнаруживает, только если изменения сделаны для заметок, а не для обнаружения нажатия клавиши. Причина этого заключается в том, что я не могу использовать "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()

спросил(а) 2021-01-19T13:30:47+03:00 6 месяцев, 1 неделя назад
1
Решение
78

Вы ищете событие <<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 избил меня снова.

ответил(а) 2021-01-19T13:30:47+03:00 6 месяцев, 1 неделя назад
78

Текстовый виджет отслеживает, был ли он изменен или нет. Вы можете запросить состояние в любое время, вызвав метод 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)

ответил(а) 2021-01-19T13:30:47+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема