2017-10-08 56 views
1

当我复制一些文字和粘贴(CRTL + V)它在一个Tkinter的条目,如果有选择的文本,它不会从条目中删除它。我在Linux(Mint)64位。
的Tkinter的复制粘贴到输入不会删除选定的文本

在这里,我复制 “d” 与(CTRL + C): enter image description here

然后我选择 “B”: enter image description here

现在我粘贴 “d”(CTRL + V)到其上但结果是这样的: enter image description here

第一:我想知道这是否是一个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() 
+0

在windows 7/python3中,粘贴按预期工作。 – Lafexlos

+0

关于选择的东西,你可以看看[这个问题](https://stackoverflow.com/questions/4073468/how-do-i-get-a-selected-string-in-from-a-tkinter-text-框)。这两个答案(及其评论)都非常翔实。 – Lafexlos

+0

@Lafexlos我已经得到了选择文本...看看我的尝试/除了。问题就像我解释的那样,并不是无法获取文本,它不知道文本从哪里来(文本在整个文本中的选择文本的索引)。 – ROAR

回答

1

这不是一个错误。如果这是一个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.firstsel.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) 
+0

非常感谢,这解决了它。无法在任何地方得到这个!我只是假设tkinter没有得到它在Linux中的应有的关注,而不是Windows。这就是为什么我认为这是一个错误。我还问了关于Linux上文件扩展名中的双点的另一个问题,并且没有任何答案(除了它在Windows上工作...所以我只是假设...) – ROAR

+0

@ROAR:相信与否,tk(the tkinter使用的底层工具包)最初是在Linux甚至存在之前为unix系统开发的。几年之后才有了一个windows和macintosh的端口。 –

+0

所以我从这里得到的是......我不能再犯错。 :D你对tkinter有很多了解......我在许多关于tkinter的问题中看到了你的答案。也许你知道[我关于文件扩展名的其他问题]的答案(https://stackoverflow.com/questions/46512663/tkinter-asksaveasfilename-doesnt-work-with-more-than-1-dot-in-file-extension )。 – ROAR

相关问题