如何在python中改变指针的位置?

问题描述 投票:0回答:2

我想在程序获取一些特殊的单词时绘制它们,实际上是实时的。 所以我写了这段代码,它做得很好,但我仍然无法使用键盘上的移动键更改指针的位置并从我移动它的位置开始输入。 谁能给我提示怎么做? 这是代码:

from colorama import init
from colorama import Fore
import sys
import msvcrt
special_words = ['test' , 'foo' , 'bar', 'Ham']
my_text = ''
init( autoreset = True)
while True:
    c = msvcrt.getch()
    if ord(c) == ord('\r'):  # newline, stop
        break
    elif ord(c) == ord('\b') :
        sys.stdout.write('\b')
        sys.stdout.write(' ')
        my_text = my_text[:-1]
        #CURSOR_UP_ONE = '\x1b[1A'
        #ERASE_LINE = '\x1b[2K'
        #print ERASE_LINE,
    elif ord(c) == 224 :
        set (-1, 1)
    else:
        my_text += c

    sys.stdout.write("\r")  # move to the line beginning
    for j, word in enumerate(my_text.split()):
        if word in special_words:
            sys.stdout.write(Fore.GREEN+ word)
        else:
            sys.stdout.write(Fore.RESET + word)
        if j != len(my_text.split())-1:
            sys.stdout.write(' ')
        else:
            for i in range(0, len(my_text) - my_text.rfind(word) - len(word)):
                sys.stdout.write(' ')
    sys.stdout.flush()
python windows pointers
2个回答
20
投票

以简单的方式做到这一点

由于您似乎已经在使用

colorama
模块,因此定位光标最简单、最便携的方法应该是使用相应的 ANSI 控制序列(请参阅:http://en.m.wikipedia.org/wiki/ ANSI_转义代码

您要查找的应该是 CUP – 光标位置 (CSI n ; m H),将光标定位在第 n 行和第 m 列。

代码将如下所示:

def move (y, x):
    print("\033[%d;%dH" % (y, x))

一切都亲力亲为,很痛苦

即使在不了解上述控制序列的 Windows 控制台中,要让事情正常工作,也是漫长而痛苦的方法,那就是使用 Windows API。

幸运的是,

colorama
模块将为您完成这项(艰苦的)工作,只要您不忘记拨打
colorama.init()

出于教学目的,我留下了最痛苦的方法的代码,省略了 colorama 模块的功能,一切都手工完成。

import ctypes
from ctypes import c_long, c_wchar_p, c_ulong, c_void_p


#==== GLOBAL VARIABLES ======================

gHandle = ctypes.windll.kernel32.GetStdHandle(c_long(-11))


def move (y, x):
   """Move cursor to position indicated by x and y."""
   value = x + (y << 16)
   ctypes.windll.kernel32.SetConsoleCursorPosition(gHandle, c_ulong(value))


def addstr (string):
   """Write string"""
   ctypes.windll.kernel32.WriteConsoleW(gHandle, c_wchar_p(string), c_ulong(len(string)), c_void_p(), None)

正如评论部分中已经指出的,这种尝试仍然给您留下了问题,您的应用程序只能在指定的控制台中运行,所以也许您仍然想提供一个

curses
版本。

要检测curses是否受支持或者你必须使用Windows API,你可以尝试这样的方法。

#==== IMPORTS =================================================================
try:
    import curses
    HAVE_CURSES = True
except:
    HAVE_CURSES = False
    pass

0
投票

根据 mikyra 和 https://stackoverflow.com/a/10455937/2059351 的答案我已经成功编译了我认为是一个完整的示例for Windows,意思是,您可以将光标移动到某个地方,打印你想要的内容,然后确保光标放回原来的位置。我希望这补充了已接受的答案。

import ctypes
from ctypes import c_ulong, c_void_p, c_wchar_p


def stdout_handle():
    return ctypes.windll.kernel32.GetStdHandle(-11)


class _Coord(ctypes.Structure):
     _fields_ = [("x", ctypes.c_short), ("y", ctypes.c_short)]


class _SmallRect(ctypes.Structure):
    _fields_ = [
        ("left", ctypes.c_short),
        ("top", ctypes.c_short),
        ("right", ctypes.c_short),
        ("bottom", ctypes.c_short),
    ]


class _ScreenBufferInfo(ctypes.Structure):
    _fields_ = [
        ("size", _Coord),
        ("cursor_pos", _Coord),
        ("attrs", ctypes.c_int),
        ("window", _SmallRect),
        ("max_window_size", _Coord),
    ]


def print_at(text: str, x: int, y: int):
    kernel32 = ctypes.windll.kernel32
    sbi = _ScreenBufferInfo()
    kernel32.GetConsoleScreenBufferInfo(stdout_handle(), ctypes.byref(sbi))
    original_position = sbi.cursor_pos

    # Adjustment is required as the values are read starting from "1", but we
    # need to

    x = x - 1
    y = y - 1

    position = x + (y << 16)
    kernel32.SetConsoleCursorPosition(stdout_handle(), position)
    kernel32.WriteConsoleW(
        stdout_handle(), c_wchar_p(text), c_ulong(len(text)), c_void_p(), None
    )
    kernel32.SetConsoleCursorPosition(stdout_handle(), original_position)
© www.soinside.com 2019 - 2024. All rights reserved.