python - 绑定(bind)到光标移动不会改变 INSERT 标记

标签 python user-interface tkinter

每次用户通过箭头、鼠标单击等更改插入点时,我都需要执行快速检查...所以我将其绑定(bind):

text.bind("<Button-1>", insertchanged)

def insertchanged(event):
    pos=text.index(INSERT)
    n=text.tag_names(INSERT)
        ...

但我发现 pos 仍然是用户更改它之前 的位置!我如何找到新位置(一个通用的解决方案,如果可能的话:我必须将它绑定(bind)到 home,end, pgup, pgdown,...)

谢谢!

最佳答案

您的方法存在几个问题。首先,您需要绑定(bind)几乎所有内容以跟踪插入点(请记住:每次插入或删除任何内容时它都会更改)。

其次,根据类绑定(bind)对小部件进行更改,默认情况下,您创建的任何绑定(bind)都将在类绑定(bind)之前触发。您可以解决这些问题,但这很棘手。例如,要绕过事件处理顺序,请在本站点和其他站点中搜索“bind tags”或“bindtags”。

但是,有一个几乎万无一失的解决方案。缺点是它需要一些严格的 Tcl 巫术:你必须用代理替换内部小部件,只要插入点发生变化,代理就会调用回调。我在下面包含了一个完整的工作示例。

import Tkinter as tk

class Example(tk.Frame):
  def __init__(self, parent):
      tk.Frame.__init__(self, parent)
      self.text = CustomText(self, wrap="word")
      self.text.pack(side="top", fill="both", expand=True)
      self.label = tk.Label(self, anchor="w")
      self.label.pack(side="bottom", fill="x")

      # this is where we tell the custom widget what to call
      self.text.set_callback(self.callback)

  def callback(self, result, *args):
      '''Updates the label with the current cursor position'''
      index = self.text.index("insert")
      self.label.configure(text="index: %s" % index)

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

        # Danger Will Robinson!
        # Heavy voodoo here. All widget changes happen via
        # an internal Tcl command with the same name as the 
        # widget:  all inserts, deletes, cursor changes, etc
        #
        # The beauty of Tcl is that we can replace that command
        # with our own command. The following code does just
        # that: replace the code with a proxy that calls the
        # original command and then calls a callback. We
        # can then do whatever we want in the callback. 
        private_callback = self.register(self._callback)
        self.tk.eval('''
            proc widget_proxy {actual_widget callback args} {

                # this prevents recursion if the widget is called
                # during the callback
                set flag ::dont_recurse(actual_widget)

                # call the real tk widget with the real args
                set result [uplevel [linsert $args 0 $actual_widget]]

                # call the callback and ignore errors, but only
                # do so on inserts, deletes, and changes in the 
                # mark. Otherwise we'll call the callback way too 
                # often.
                if {! [info exists $flag]} {
                    if {([lindex $args 0] in {insert replace delete}) ||
                        ([lrange $args 0 2] == {mark set insert})} {
                        # the flag makes sure that whatever happens in the
                        # callback doesn't cause the callbacks to be called again.
                        set $flag 1
                        catch {$callback $result {*}$args } callback_result
                        unset -nocomplain $flag
                    }
                }

                # return the result from the real widget command
                return $result
            }
            ''')
        self.tk.eval('''
            rename {widget} _{widget}
            interp alias {{}} ::{widget} {{}} widget_proxy _{widget} {callback}
        '''.format(widget=str(self), callback=private_callback))

    def _callback(self, result, *args):
        self.callback(result, *args)

    def set_callback(self, callable):
        self.callback = callable


if __name__ == "__main__":
  root = tk.Tk()
  frame = Example(root)
  frame.pack(side="top", fill="both", expand=True)
  root.mainloop()

关于python - 绑定(bind)到光标移动不会改变 INSERT 标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13835207/

相关文章:

C 程序,用户输入到单个数组中

c++ - 这个基本 MFC 对话框应用程序的入口点是什么?

python - 了解分发卡住的 Python Tkinter 应用程序需要 TCL 中的哪些文件

multithreading - tkinter tkMessageBox 不能在线程中工作

python - 为 Sympy 解决方案建议解决方案

python - 将 float 转换为 int 时,尾随数字从何而来?

c++ - 如何在 C++ 中嵌入 Chromium 嵌入式框架

python - tkinter网格行没有出现并且没有传递到正确的功能

python - 匹配文本中存储的关键字/短语

python - 将 Django-Storages 与亚马逊 S3 和 https 一起使用