【问题标题】:tkinter prevent deletion of selected text with return keytkinter 防止使用返回键删除选定的文本
【发布时间】:2013-09-02 08:46:03
【问题描述】:

我正在实现一个基于 tkinter 文本小部件的控制台应用程序,作为自动完成功能的一部分,我观察到一个问题,即按返回键会导致删除所选文本。下面的例子显示了类似的问题:

from Tkinter import *

def getCommand(*args):
    global text
    text.insert(END, "\n")
    text.insert(END, "command>")
    x = text.get("1.0",END)
    print "command is %s" %(x)
    return 'break'

def handle_keyrelease(event):
    global text
    if event.keysym == "Return":
        text.tag_remove(SEL,"1.9",END)
        text.mark_set("insert",END)
        getCommand()
        return 'break'

root = Tk()
text = Text(root)
text.pack()
text.insert(END,"command>")
text.focus()
text.bind("<KeyRelease>", handle_keyrelease)
text.insert(END,"sometext")
text.tag_add(SEL,"1.9",END)
text.mark_set("insert","1.9") 
root.mainloop()

在这段代码中,当我按回车键时,我想获得完整的命令sometext,但是使用当前代码只检索到s。当收到返回键事件时,我尝试将光标位置设置为结束并删除选择标签。

编辑

KeyPress 事件处理程序的问题:

from Tkinter import *

def getCommand(*args):
    global text
    text.insert(END, "\n")
    text.insert(END, "command>")
    x = text.get("1.0",END)
    print x
    return 'break'

validkeysymchars = []
validkeysymchars = validkeysymchars + map(chr, range(65,91))
validkeysymchars = validkeysymchars + map(chr, range(97,123))

def handle_keyrelease(event):
    global text
    if event.keysym == "Return":
        text.tag_remove(SEL,"1.9",END)
        text.mark_set("insert",END)
        getCommand()
        return 'break'
    if event.keysym in validkeysymchars:
        for x in ['testcommand']:
            strtocmp = text.get("MARK","end")
            strtocmp = strtocmp.encode('ascii','ignore')
            strtocmp = strtocmp.strip()
            print strtocmp
            if x.startswith(strtocmp):
                currpos = text.index(INSERT)
                text.insert(END,x[len(strtocmp):])
                text.tag_add(SEL,currpos,"%s+%dc"%(currpos,len(x)-len(strtocmp)))
                text.mark_set("insert",currpos)   

root = Tk()
text = Text(root)
text.pack()
text.insert(END,"command>")
text.mark_set("MARK",INSERT)
text.mark_gravity("MARK",LEFT)
text.focus()
text.bind("<KeyPress>", handle_keyrelease)
root.mainloop()

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    问题在于您处理的是&lt;KeyRelease&gt; 而不是&lt;KeyPress&gt;(或&lt;Return&gt;)。

    在引发&lt;KeyRelease&gt; 事件时,文本小部件已经更新为换行符。并且因为选择了文本,所以选择的文本被简单地替换为换行符(因为它会被按任何其他键替换)。

    所以最好绑定到&lt;KeyPress&gt;&lt;Return&gt; 而不是&lt;KeyRelease&gt;


    我认为解决您的问题的最简单方法确实是分别处理&lt;KeyRelease&gt;&lt;Return&gt;

    (您可以使用&lt;KeyPress&gt; 使其工作,但这将涉及检查按下哪个键,手动将此键插入文本,检查选择了哪些文本,并替换选定的文本;因此,它将是相当笨重)。

    def handle_keyrelease(event):
        global text
        if event.keysym in validkeysymchars:
            for x in ['testcommand']:
                strtocmp = text.get("MARK","end")
                strtocmp = strtocmp.encode('ascii','ignore')
                strtocmp = strtocmp.strip()
                print strtocmp
                if x.startswith(strtocmp):
                    currpos = text.index(INSERT)
                    text.insert(END,x[len(strtocmp):])
                    text.tag_add(SEL,currpos,"%s+%dc"%(currpos,len(x)-len(strtocmp)))
                    text.mark_set("insert",currpos)
                    return
    
    def handle_return(event):
        text.tag_remove(SEL,"1.9",END)
        text.mark_set("insert",END)
        text.insert(END, "\n")
        text.insert(END, "command>")
        text.mark_set("MARK",INSERT)
        text.mark_gravity("MARK",LEFT)
        return "break"
    
    ...
    text.bind("<KeyRelease>", handle_keyrelease)
    text.bind("<Return>", handle_return)
    ...
    

    【讨论】:

    • 实际上,我首先使用了KeyPress 事件处理程序,但我遇到了另一个奇怪的问题。我的自动完成代码没有与KeyPress 事件处理程序一起运行,并迫使我使用KeyRelease 处理程序。我已经更新了我的代码,您能否评论一下为什么它不能与 KeyPress 事件处理程序一起使用。只需在文本小部件上输入t,您会注意到在KeyRelease 的情况下,它将在文本小部件中插入testcommand,而KeyPress 则没有任何反应。
    • KeyPress 的情况下,只有在插入新字符后才会读取前一个键。那么唯一的解决方案是使用KeyRelease 自动完成并使用KeyPress 作为Return 键还是可以以更有效的方式处理?
    • @sarbjit 您确实可以使用单个&lt;KeyPress&gt; 处理程序,但这会相当丑陋和复杂。最好使用两个单独的处理程序。查看我的编辑。
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2011-01-17
    • 2013-06-05
    • 1970-01-01
    • 2015-04-03
    • 2012-06-18
    • 1970-01-01
    相关资源
    最近更新 更多