的Tkinter的复制粘贴到输入不会删除选定的文本
当我复制一些文字和粘贴(CRTL + V)它在一个Tkinter的条目,如果有选择的文本,它不会从条目中删除它。我在Linux(Mint)64位。
的Tkinter的复制粘贴到输入不会删除选定的文本
现在我粘贴 “d”(CTRL + V)到其上但结果是这样的:
第一:我想知道这是否是一个bug具体到Linux或这是它是如何应该是什么?
二:我在想一个解决方法为这个与validatecommand
但我得到了另外一个问题:
如果我要删除命令选定的文本,我必须知道选择的指数入口。否则,如果有直接后光标之前所选文本的多个实例,我不知道要删除哪一个,并用新的文本替换。因为光标可以是该选择的任一侧(取决于如果该人被拖动到左侧或从左向右上的文本的形式鼠标右)。
现在有没有办法让指数的选择在入门?或另一种方法来解决这个问题?
下面是一些代码有问题的例子:
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()
这不是一个错误。如果这是一个bug,有人会在十年前注意到它并修复它。 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
}
}
使用的验证功能肯定是要解决这种错误的方式。验证是专门为名称暗示的:验证。正确的解决方案是创建自己的绑定到<<Paste>>
事件。
现在有办法让条目中的选择索引?或另一种方法来解决这个问题?
是,输入构件具有代表在选择的第一个字符的特殊指标sel.first
和sel.last
仅代表选择之后的字符。
一个上面的代码为蟒蛇(减去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"
为了有这个适用于特定的部件,绑定到<<Paste>>
事件为小工具:
entry = tk.Entry(...)
entry.bind("<<Paste>>", custom_paste)
如果你想做到这一点适用于所有的Entry
部件的单一绑定,使用bind_class
:
root = tk.Tk()
...
root.bind_class("Entry", "<<Paste>>", custom_paste)
非常感谢,这解决了它。无法在任何地方得到这个!我只是假设tkinter没有得到它在Linux中的应有的关注,而不是Windows。这就是为什么我认为这是一个错误。我还问了关于Linux上文件扩展名中的双点的另一个问题,并且没有任何答案(除了它在Windows上工作...所以我只是假设...) – ROAR
@ROAR:相信与否,tk(the tkinter使用的底层工具包)最初是在Linux甚至存在之前为unix系统开发的。几年之后才有了一个windows和macintosh的端口。 –
所以我从这里得到的是......我不能再犯错。 :D你对tkinter有很多了解......我在许多关于tkinter的问题中看到了你的答案。也许你知道[我关于文件扩展名的其他问题]的答案(https://stackoverflow.com/questions/46512663/tkinter-asksaveasfilename-doesnt-work-with-more-than-1-dot-in-file-extension )。 – ROAR
在windows 7/python3中,粘贴按预期工作。 – Lafexlos
关于选择的东西,你可以看看[这个问题](https://stackoverflow.com/questions/4073468/how-do-i-get-a-selected-string-in-from-a-tkinter-text-框)。这两个答案(及其评论)都非常翔实。 – Lafexlos
@Lafexlos我已经得到了选择文本...看看我的尝试/除了。问题就像我解释的那样,并不是无法获取文本,它不知道文本从哪里来(文本在整个文本中的选择文本的索引)。 – ROAR