Python Curses - 检测退格键

6

我在使用Curses模块检测Backspace键时遇到了困难。每当我按下Backspace键,返回的字符/字符串是'^?',但我无法通过以下代码进行检测:

if str(key) == '^?':

以下代码已经准备就绪。

import curses

def main(win):
    win.nodelay(True)
    key = ''
    record = ''
    win.clear()
    win.addstr("Key:")
    win.addstr('\n\nRecord:')
    win.addstr(record)
    while True:
        try:
            key = win.getkey()

            if str(key) == '^?':
                # Attempt at detecting the Backspace key
                record = record[:-1]

            elif str(key) == '\n':
                # Attempt at detecting the Enter Key
                record = ''

            else:
                record += str(key)
            win.clear()
            win.addstr("Key:")
            win.addstr(str(key))
            win.addstr('\n\nRecord:')
            win.addstr(record)
            if key == os.linesep:
                break
        except Exception as e:
            # No input
            pass

curses.wrapper(main)
# CTRL+C to close the program

2
当你按下退格键时,type(key)repr(key)会输出什么? - ssokolow
类型(key): <class 'str'> 表示(key): '\x7f' - Neil Graham
当我按退格键时,ord(key) 返回 127,我用它来检测退格键。 - Neil Graham
4个回答

6
根据您的澄清评论,您终端中的退格键既不是'KEY_BACKSPACE'也不是'\b'('\x08')。
由于您正在使用curses.wrapper(),它调用curses.initscr(),这表明您的terminfo数据库(不太可能)或终端配置(更有可能)存在问题。
getkey() == 'KEY_BACKSPACE'或getch() == curses.KEY_BACKSPACE应该在任何正确配置的系统上都能正常工作,因此您可能在其他应用程序中也会遇到问题。
TERM环境变量是将终端类型传递给需要超出基本电传功能的工具的方式,因此要修复它,请首先检查在运行Python的环境中TERM环境变量包含什么。
print(os.environ['TERM'])

作为一个快速的hack方法,您可以检查它所观察到的所有值。
if key in ('KEY_BACKSPACE', '\b', '\x7f'):

对于尝试旧版本的“快速hack”的任何人,我感到抱歉。我在脑海中混淆了getkey()getch() - ssokolow
2
通过执行 ord(key),返回整数 127,因此我能够使用它来检测退格键。 - Neil Graham
1
记录一下,ord('\x7f') == 127 - ssokolow
1
127 不是代表删除键吗?(curses.ascii.DEL == 127)? - schneiderfelipe

3
在我的机器上,运行Python 3.5.2或2.7.12时,当我按下退格键时,我看到KEY_BACKSPACE被显示,并使用。
if str(key) == 'KEY_BACKSPACE':

代替
if str(key) == '^?':

退格键导致record中的字母被删除。

我认为在您的系统上,您可能得到了实际的退格字符。在这种情况下,您可以尝试使用'\b'代替'^?',因为根据文档,这是ASCII退格字符的字符串转义。


你使用什么? - user1767754
很遗憾,这两个对我都不起作用。我正在使用macOS v10.13.1。 - Neil Graham
1
if getch() in [KEY_BACKSPACE, ord('\b')] 对我有效。 - Vapid

2
在MacOS上,请尝试以下操作:
    key = w.getch()
    if key == 127:
        print("You've pressed Backspace")

0

查看源代码,文本框 Textbox.edit() 方法只会在按下 curses.ascii.BScurses.ascii.BACKSPACE 时删除一个字符(例如 curses.delch)。至少在 MacOS 上,delete 键注册为 curses.ascii.DEL

我们可以传递一个自定义的 validate() 来重载此功能,例如在 DELETE 上执行 backspace,在 ESCAPE 上执行退出,在 RESIZE 上执行退出:

import curses
import curses.textpad

def get_input(window):
    curses.curs_set(1)
    curses.set_escdelay(1)
    window.addstr(0, 0, "Enter some text:")
    input_box = curses.textpad.Textbox(curses.newwin(1, 40, 1, 0), insert_mode=True)
    
    def validate(ch):

            # exit input with the escape key
            escape = 27
            if ch == escape:
                ch = curses.ascii.BEL # Control-G
            
            # delete the character to the left of the cursor
            elif ch in (curses.KEY_BACKSPACE, curses.ascii.DEL):
                ch = curses.KEY_BACKSPACE
            
            # exit input to resize windows
            elif ch == curses.KEY_RESIZE:
                ch = curses.ascii.BEL # Control-G

            return ch
    
    input_box.edit(validate)
    curses.curs_set(0)
    curses.set_escdelay(1000)
    return input_box.gather().strip()


def main(window):
    curses.noecho()
    curses.cbreak()
    window.keypad(True)
    curses.curs_set(0)

    input_text = get_input(window)

    window.addstr(2, 0, f"You entered: {input_text}")
    window.refresh()
    window.getch()

if __name__ == "__main__":
    curses.wrapper(main)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接