检测TextBox何时被编辑而不是检测按键?

时间:2017-06-23 19:29:41

标签: python tkinter

我有一个笔记记录程序,只需按一下按钮即可在笔记之间切换。这对我来说很方便。我有一点内置安全性,当我在文本框中有活动音符时,按下键盘上的任何键,然后在文本框内,然后尝试选择一组不同的音符,它会问我是否要更改音符而不用节省。

这很好用但是我需要找到一种方法,它只检测是否对音符进行了更改而不是检测按键。原因是我无法使用"CTRL-C"复制我的笔记部分,而不会启动导致弹出警告的事件。我希望能够继续从一组笔记跳转到另一组笔记,除非对TextBox内的文本进行了编辑。

如果您尝试使用"CTRL-C"复制任何突出显示的文字,那么您会看到尝试切换笔记也会询问您是否确定要切换。我试图避免这种情况,我认为应该有一种方法来检查注释是否有任何更改,而不是检测TextBox中的keypress

我尝试将textvariabletrack一起使用,但是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()

2 个答案:

答案 0 :(得分:2)

文本小部件会跟踪它是否已被修改。您可以通过调用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)

答案 1 :(得分:2)

您正在寻找<<Modified>>事件。

但是,您不需要为此烦恼,因为Text小部件本身会保留一个修改过的标志。这是一个例子(还有许多其他代码建议):

# 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()

编辑:Dammit Bryan再次击败我。