当我复制一些文本并将其粘贴 (crtl + v) 到 tkinter Entry 中时,如果有选定的文本,它不会将其从条目中删除。我在 Linux (Mint) 64 位上。
现在我将“d”(ctrl + v)粘贴到它上面,但结果是这样的:
首先:我想知道这是 Linux 特有的错误还是应该如此?
第二:我正在考虑使用 validatecommand
解决此问题,但我遇到了另一个问题:
如果我要在命令中删除选定的文本,我必须知道条目中选择的索引。否则,如果在光标前后直接有多个选定文本实例,我将不知道要删除哪一个并用新文本替换。因为光标可能位于所选内容的任一侧(取决于用户是在文本上从右向左还是从左向右拖动鼠标)。
现在有办法获取条目中selection的index吗?或其他解决此问题的方法?
下面是一些带有问题示例的代码:
import tkinter as tk
root = tk.Tk()
def validation(after_text, before_text, validation_text, cursor_index):
cursor_index = int(cursor_index)
print('cursor index:', cursor_index)
print('text after change:', after_text)
print('text before change:', before_text)
print('text in need of validation:', validation_text)
try:
selection = root.selection_get()
except:
selection = ''
print('selection:', selection)
# EXAMPLE:
# validation_text = 'd'
# before text = "bb"
# now if someone dragged from right to left on the 2nd b:
# cursor position will be 1 (imagine | as the cursor): 'b|b'
# cursor_index = 1
# after_text = 'bdb' --> but should be 'bd'
# now if someone dragged from left to right on the 2nd b:
# cursor position will be 2 (imagine | as the cursor): 'bb|'
# cursor_index = 2
# after_text = 'bbd' --> but should be 'bd'
# so there is no way for me to know which of these b's I have
# to replace with d based on cursor position alone. I have to
# know the index of selection itself in before_text to be
# able to replace the text properly.
# I don't know how to get that.
return True
txtvar = tk.StringVar(value = 'a-b-c-d-e')
entry = tk.Entry(root, textvariable = txtvar)
font = tk.font.Font(family = entry.cget('font'), size = -50)
entry.config(validate = 'all',
vcmd = (root.register(validation),'%P', '%s', '%S', '%i'),
font = font)
entry.pack()
root.mainloop()
最佳答案
这不是错误。如果它是一个错误,十年前就会有人注意到它并修复它。 Tkinter 已经存在很长时间了,像这样的基本事物不会被忽视。
在基于 X11 的系统上实现粘贴不会在粘贴前删除选定的文本。以下是截至我撰写本文时实际的底层 Tcl 代码:
bind Entry <<Paste>> {
global tcl_platform
catch {
if {[tk windowingsystem] ne "x11"} {
catch {
%W delete sel.first sel.last
}
}
%W insert insert [::tk::GetSelection %W CLIPBOARD]
tk::EntrySeeInsert %W
}
}
使用验证功能肯定是解决这个问题的错误方法。 Validation 顾名思义就是:validation。正确的解决方案是创建您自己的绑定(bind)到 <<Paste>>
事件。
Now is there a way to get the index of selection in the entry? or another way to workaround this problem?
是的,条目小部件具有特殊索引 sel.first
表示选择中的第一个字符,sel.last
表示选择后的字符。
将上述代码直接翻译成 python(减去对 x11 的检查)看起来像这样:
def custom_paste(event):
try:
event.widget.delete("sel.first", "sel.last")
except:
pass
event.widget.insert("insert", event.widget.clipboard_get())
return "break"
要将其应用于特定小部件,请绑定(bind)到 <<Paste>>
该小部件的事件:
entry = tk.Entry(...)
entry.bind("<<Paste>>", custom_paste)
如果你想做一个适用于每个 Entry
的单一绑定(bind)小部件,使用 bind_class
:
root = tk.Tk()
...
root.bind_class("Entry", "<<Paste>>", custom_paste)
关于linux - tkinter 复制粘贴到 Entry 不会删除选定的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46634858/