【问题标题】:reading arrow keys without Curses module阅读没有诅咒模块的箭头键
【发布时间】:2018-12-18 22:13:07
【问题描述】:

所以我正在制作一个需要箭头键但不能使用 curses 或 chr 功能的程序。有什么简单易行的方法吗?

顺便说一句,我已经尝试过inp.key_UP,但这似乎不起作用。我也在mac上,所以gtsrc不能工作。

【问题讨论】:

  • 为什么不能使用chr函数?我认为限制是老师某些任务的一部分;否则它几乎没有意义。那么,你能给我们完整的任务描述吗?
  • 另外,inp.key_UP 是什么?我假设那来自某个第三方库? glsrc 是什么?
  • 我不能使用 chr 函数,因为我已经有 w、a、s 和 d 作为用户的输入,并且我无法更改该输入的变量以包含 chr,因为那时 w 、a、s 和 d 不起作用,因为它们不是数字。
  • 对不起,我不明白你的意思。 chr(119)'w'
  • 那么箭头键的顺序是什么

标签: python python-3.x module arrow-keys


【解决方案1】:

当用户按下一个键时(除非您正在阅读非常低的级别,例如 Cocoa 系统事件挂钩),终端程序(通常是 Terminal.app)会处理该按键并向您的程序发送一个字节序列,您可以阅读sys.stdin/dev/tty

假设默认设置:

  • 对于 ASCII 字母、数字等,该字节序列只有一个字节,带有字符的 ord
  • 对于非 ASCII 字符,该字节序列是字符的 UTF-8 编码。 (在其他 *nix 上,您不能依赖它是 UTF-8,但在 macOS 上,您可以。)
  • 对于箭头等特殊键,该序列为ANSI standard escape sequences。例如,对于向上箭头,您将获得 Cursor Up (\x1b[A),或者 Cursor Up 1 (\x1b[1A)。 (你真的不应该假设一个 ANSI 兼容的终端——你甚至可以配置 Terminal.app 来发送不同的东西——而是阅读$TERM 并查找 termcaps 条目,但如果你只关心 Mac,你会几乎可以肯定地逃脱了这一点。)

所以,现在您只需将 stdin/dev/tty 作为无缓冲的原始二进制文件打开,将其置于原始模式(并确保在程序结束时恢复它),从中读取字节,并识别 ANSI 控制序列。哦,如果用户的键盘有任何不是 ASCII 的键,它们也会显示为多个字节,您必须将其解码为 UTF-8。

这里有一些东西应该证明它:

import termios
import tty

with open('/dev/tty', 'rb', buffering=0) as f:
    stashed = termios.tcgetattr(f.fileno())
    try:
        tty.setraw(f.fileno())
        while True:
            key = f.read(1)
            if key == b'\x03': # Control-C
                break
            if key == b'\x1b': # Escape
                buf = key
                while True:
                    key = f.read(1)
                    buf += key
                    # Cheating a bit; most sequences go until the first letter
                    if key.isalpha():
                        break
                if buf == b'\x1b[A':
                    print('Up arrow!')
                else:
                    print('Some other control sequence:', buf)
            # punting on UTF-8 decoding, treating non-ASCII as control chars
            elif b' ' <= key < b'\x80':
                print(key.decode())
            else:
                print('Some control or non-ASCII key', key)
    finally:
        termios.tcsetattr(f.fileno(), termios.TCSADRAIN, stashed)

如果这不能说明为什么人们通常使用像 curses 这样的更高级别的库,那么请寻找一些实际上正确执行 termcap 和 locale 内容的代码,而不是假设。 :)

【讨论】:

    【解决方案2】:

    我试着... 但是,您需要按 Enter 键才能返回该值。 祝你好运!

    import sys
    
    def get():
        x = sys.stdin.read(1)
        return x
    while True: 
    
        key = get()
        print key
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      • 2017-08-02
      • 2014-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多