在 tkinter 条目上的单击事件中更改光标位置

change cursor location in click event on tkinter entry

我试图在单击条目内部时更改鼠标指针位置。我在输入时使用了 icursor 方法,但它没有用。

我希望指针移动到位置 0,当我在条目内单击时。

from tkinter import *
from tkinter import ttk


def on_click(event):
    event.widget.icursor(0)  # this will not move cursor to the first place

root = Tk()

e = ttk.Entry(root)
e.pack()

e.insert(0, "Hello World")

e.bind("<1>", on_click)

root.mainloop()

因此,当我在条目中单击时,我希望鼠标指针移动到第一个 (icursor(0)),但它不起作用。

actullay 如果我得到鼠标指针位置,它就可以工作 python 会看到它在 0 位置,但指针本身不在位置 0。

print(e.index(INSERT))

有人知道如何解决这个问题吗?

这是由于在 Tkinter 中处理事件的顺序。

有关详细说明,请阅读 this answer,但简而言之,事件是按 bindtags 的顺序处理的。要查看这些是什么,您可以 print(e.bindtags()) 打印出

('.!entry', 'TEntry', '.', 'all')

这里.!entry是当前widgeteTEntry是ttk Entryclass,.是widget的Toplevel或Tk实例,all 是一个可以绑定到所有小部件都有的标签。

现在,当您执行 e.bind("<1>", on_click) 时,您将 on_click 函数绑定到小部件 e。当您单击该小部件时,首先调用您的 on_click 函数,将光标置于开头,然后调用 ttk 输入框的默认事件。 ttk Entry 的默认事件继承自标准 Tkinter Entry,根据 the manual,它是

Clicking mouse button 1 positions the insertion cursor just before the character underneath the mouse cursor, sets the input focus to this widget, and clears any selection in the widget. Dragging with mouse button 1 strokes out a selection between the insertion cursor and the character under the mouse.

因此,即使您确实 将光标放在位置 0,鼠标按钮的默认 Entry 事件是将光标的位置更改为您单击的位置。因为这是处理事件的顺序,所以您永远不会在位置 0 看到光标。

但是,您可以在处理完默认事件后添加一个事件。为此,您可以在 class 之后添加一个 bindtag 并绑定到它:

e.bindtags(((str(e)), "TEntry", "post-click", ".", "all"))
e.bind_class("post-click", "<1>", on_click)

通过这种方式,您可以将回调绑定到在上述引用中提到的所有这些操作之后处理的标记,因此您会看到光标位于位置 0。

请记住,这会影响所有点击,包括双击、三次点击、按住 control 键的点击……
(顺便说一下,不是拖动,因为它以 <ButtonRelease-1> 事件结束)。

备用解决方案

def on_click(event):
    root.after_idle(event.widget.icursor, 0)

Source