Python 当我更改当前插入位置时,如何在Tkinter中回拨

Python 当我更改当前插入位置时,如何在Tkinter中回拨,python,events,user-interface,text,tkinter,Python,Events,User Interface,Text,Tkinter,嗨,我正在做一个与Python Tkinter共同编辑的项目。我需要捕获用户更改插入索引位置时的事件。我使用Tkinter.Text作为控件。现在我只能捕获虚拟事件,但是如何检测用户是否在不修改内容的情况下更改了编辑位置? 提前多谢了有点奇怪,Tkinter没有直接内置的东西来解决这个问题。然而,仍然有一种方法可以做你想做的事。诀窍是用文本小部件截获所有低级活动,然后生成应用程序可以绑定到的事件 例如,要在插入光标移动时获得通知,您需要在插入或删除某个内容或插入光标发生更改时生成事件(通过标记集

嗨,我正在做一个与Python Tkinter共同编辑的项目。我需要捕获用户更改插入索引位置时的事件。我使用Tkinter.Text作为控件。现在我只能捕获
虚拟事件,但是如何检测用户是否在不修改内容的情况下更改了编辑位置?
提前多谢了

有点奇怪,Tkinter没有直接内置的东西来解决这个问题。然而,仍然有一种方法可以做你想做的事。诀窍是用文本小部件截获所有低级活动,然后生成应用程序可以绑定到的事件

例如,要在插入光标移动时获得通知,您需要在插入或删除某个内容或插入光标发生更改时生成事件(通过
标记集插入
命令)

我们可以设置一个代理来拦截所有这些命令。代理将把命令转发给原始的widget对象,当它检测到将改变插入点的命令时生成一个事件,然后返回原始命令的结果

以下是一个工作示例:

# for python3, use 'tkinter' instead of 'Tkinter'
import Tkinter as tk  

class Example(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.text = CustomText(self, background="white")
        self.status = tk.Label(self, bd=1, relief='sunken', text="", anchor="w")
        self.status.pack(side="bottom", fill="x")
        self.text.pack(side="right", fill="both", expand=True)

        self.text.bind("<<CursorChange>>", self._on_change)

        self.text.insert("end", "one\ntwo\nthree\n")
        self.text.insert("end", "four\n",("bigfont",))
        self.text.insert("end", "five\n")

    def _on_change(self, event):
        line, char = self.text.index("insert").split(".")
        message = "Line: %s character: %s" % (line, char)
        self.status.configure(text=message)


class CustomText(tk.Text):
    def __init__(self, *args, **kwargs):
        tk.Text.__init__(self, *args, **kwargs)

        # create a proxy for the underlying widget
        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)

    def _proxy(self, *args):
        cmd = (self._orig,) + args
        result = self.tk.call(cmd)

        # generate an event if something was added or deleted,
        # or the cursor position changed
        if (args[0] in ("insert", "delete") or 
            args[0:3] == ("mark", "set", "insert")):
            self.event_generate("<<CursorChange>>", when="tail")

        return result        


if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True);
    root.mainloop()
#对于python3,请使用“tkinter”而不是“tkinter”
将Tkinter作为tk导入
类示例(tk.Frame):
定义初始化(self,*args,**kwargs):
tk.Frame.\uuuu init\uuuuu(self,*args,**kwargs)
self.text=自定义文本(self,background=“白色”)
self.status=tk.Label(self,bd=1,relief='sinken',text=,anchor=“w”)
自我状态包装(side=“bottom”,fill=“x”)
self.text.pack(side=“right”,fill=“both”,expand=True)
self.text.bind(“,self.\u on\u change)
self.text.insert(“结束”、“一个\n两个\n树”)
self.text.insert(“end”、“four\n”、“bigfont”))
self.text.insert(“end”,“five\n”)
更改时的定义(自身、事件):
行,char=self.text.index(“插入”).split(“.”)
message=“行:%s字符:%s”%(行,字符)
self.status.configure(文本=消息)
类CustomText(tk.Text):
定义初始化(self,*args,**kwargs):
tk.Text.\uuuu init\uuuuu(self,*args,**kwargs)
#为基础小部件创建代理
self._orig=self._w+“_orig”
self.tk.call(“重命名”,self.\w,self.\u orig)
self.tk.createcommand(self.\u w,self.\u代理)
def_代理(self,*args):
cmd=(自身源代码,)+args
结果=self.tk.call(cmd)
#如果添加或删除了某些内容,则生成事件,
#或者光标位置改变了
如果(参数[0]在(“插入”、“删除”)中,或
args[0:3]==(“标记”、“设置”、“插入”):
self.event_generate(“,when=“tail”)
返回结果
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
示例(root).pack(fill=“both”,expand=True);
root.mainloop()

令人惊讶的是,Tkinter没有直接内置的解决方案。然而,仍然有一种方法可以做你想做的事。诀窍是用文本小部件截获所有低级活动,然后生成应用程序可以绑定到的事件

例如,要在插入光标移动时获得通知,您需要在插入或删除某个内容或插入光标发生更改时生成事件(通过
标记集插入
命令)

我们可以设置一个代理来拦截所有这些命令。代理将把命令转发给原始的widget对象,当它检测到将改变插入点的命令时生成一个事件,然后返回原始命令的结果

以下是一个工作示例:

# for python3, use 'tkinter' instead of 'Tkinter'
import Tkinter as tk  

class Example(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.text = CustomText(self, background="white")
        self.status = tk.Label(self, bd=1, relief='sunken', text="", anchor="w")
        self.status.pack(side="bottom", fill="x")
        self.text.pack(side="right", fill="both", expand=True)

        self.text.bind("<<CursorChange>>", self._on_change)

        self.text.insert("end", "one\ntwo\nthree\n")
        self.text.insert("end", "four\n",("bigfont",))
        self.text.insert("end", "five\n")

    def _on_change(self, event):
        line, char = self.text.index("insert").split(".")
        message = "Line: %s character: %s" % (line, char)
        self.status.configure(text=message)


class CustomText(tk.Text):
    def __init__(self, *args, **kwargs):
        tk.Text.__init__(self, *args, **kwargs)

        # create a proxy for the underlying widget
        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)

    def _proxy(self, *args):
        cmd = (self._orig,) + args
        result = self.tk.call(cmd)

        # generate an event if something was added or deleted,
        # or the cursor position changed
        if (args[0] in ("insert", "delete") or 
            args[0:3] == ("mark", "set", "insert")):
            self.event_generate("<<CursorChange>>", when="tail")

        return result        


if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True);
    root.mainloop()
#对于python3,请使用“tkinter”而不是“tkinter”
将Tkinter作为tk导入
类示例(tk.Frame):
定义初始化(self,*args,**kwargs):
tk.Frame.\uuuu init\uuuuu(self,*args,**kwargs)
self.text=自定义文本(self,background=“白色”)
self.status=tk.Label(self,bd=1,relief='sinken',text=,anchor=“w”)
自我状态包装(side=“bottom”,fill=“x”)
self.text.pack(side=“right”,fill=“both”,expand=True)
self.text.bind(“,self.\u on\u change)
self.text.insert(“结束”、“一个\n两个\n树”)
self.text.insert(“end”、“four\n”、“bigfont”))
self.text.insert(“end”,“five\n”)
更改时的定义(自身、事件):
行,char=self.text.index(“插入”).split(“.”)
message=“行:%s字符:%s”%(行,字符)
self.status.configure(文本=消息)
类CustomText(tk.Text):
定义初始化(self,*args,**kwargs):
tk.Text.\uuuu init\uuuuu(self,*args,**kwargs)
#为基础小部件创建代理
self._orig=self._w+“_orig”
self.tk.call(“重命名”,self.\w,self.\u orig)
self.tk.createcommand(self.\u w,self.\u代理)
def_代理(self,*args):
cmd=(自身源代码,)+args
结果=self.tk.call(cmd)
#如果添加或删除了某些内容,则生成事件,
#或者光标位置改变了
如果(参数[0]在(“插入”、“删除”)中,或
args[0:3]==(“标记”、“设置”、“插入”):
self.event_generate(“,when=“tail”)
返回结果
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
示例(root).pack(fill=“both”,expand=True);
root.mainloop()

令人惊讶的是,Tkinter没有直接内置的解决方案。然而,仍然有一种方法可以做你想做的事。诀窍是用文本小部件截获所有低级活动,然后生成应用程序可以绑定到的事件

例如,要在插入光标移动时获得通知,您需要在插入或删除某个内容或插入光标发生更改时生成事件(通过
标记集插入
命令)

我们可以设置一个代理来拦截所有这些命令。代理将把命令转发给原始的widget对象,当它检测到一个命令将改变控件时生成一个事件