我正在运行 Python 3.10,并且遇到了诅咒问题,特别是在尝试利用全部颜色对时
curses.COLORS
返回256
curses.COLOR_PAIRS
返回65536
curses.has_extended_color_support()
返回True
但是当我初始化 256、512、768、1024 等颜色对时...该颜色对似乎重置了初始化的颜色
此外,如果我尝试显示任何颜色对 > 255 (
curses.COLORS - 1
),它会使用其中一对 < 255 instead of the color pair ID I set. Curses allows me to run init_pair with these numbers, but it ignores them completely, and instead uses the color pair < 255
这是一个示例代码片段
#!/usr/bin/env python3.10
"""
Python3.10 added extended color support to curses
curses.COLOR_PAIRS (xterm-256color) returns 65,536
curses.COLORS (xterm-256color) returns 256
"""
import curses
def cycler(start_color, end_color):
# cycle through all possible color IDs or pair IDs curses can display, loops indefinitely
while True:
for i in range(start_color, end_color):
yield i
def main(stdscr):
curses.start_color()
height, width = stdscr.getmaxyx()
RED = 1 # Reserve the red color at color ID 1
curses.init_color(RED, 1000, 0, 0)
color_cycler = cycler(2, curses.COLORS - 1) # RED is reserved at 1, start at 2
pair_cycler = cycler(1, curses.COLOR_PAIRS - 1)
has_extended_support = curses.has_extended_color_support()
stdscr.addstr(0, 0, f"COLORS:{curses.COLORS} "
f"COLOR_PAIRS:{curses.COLOR_PAIRS} "
f"ExtendedSupport:{has_extended_support}", curses.color_pair(1))
for y in range(1, height - 1):
for x in range(0, width, 5):
color_id = next(color_cycler)
pair_id = next(pair_cycler)
intensity = int((color_id / (curses.COLORS - 1)) * 1000)
curses.init_color(color_id, intensity, intensity, intensity)
# create a new color pair, (RED) foreground, (color) background
curses.init_pair(pair_id, RED, color_id)
string = str(pair_id).rjust(5, ' ')
stdscr.addstr(y, x, string, curses.color_pair(pair_id))
stdscr.noutrefresh()
curses.doupdate()
stdscr.getch()
if __name__ == "__main__":
curses.wrapper(main)
这是它为我生成的屏幕截图(注意数字 256、512、768、1024) 数字代表颜色对 ID
我尝试过的终端应用程序:
大家都有同样的问题
您必须使用 extended 接口,如 ncurses 6.1 的发布公告中所述:
进行此扩展的动机来自于注意到 termcap 应用程序可以(尽管不现实)使用比 16 位更大的数字,并且 256 色 xterm 的颜色对数量无法用terminfo(即 32767 与 65536)。此外,一些终端支持直接颜色,可以使用扩展。
Python 可能不会这样做(它的绑定仅覆盖 ncurses 的一部分),因此颜色值和颜色对是一个带符号的 16 位数字:
0..32767
现在... python 3.10 已于 2021 年 10 月发布。与颜色对相关的最新 ncurses 修复是在 2021 年 8 月。如果您使用旧版本的 ncurses(例如,通过在非常旧的东西上编译 python,例如 RHEL8),那么这只是一个已知的错误,答案将是“升级”。
我创建了上述示例的 C++ 版本。不知道是否正确。
#include <ncurses.h>
#include <iterator>
#include <chrono>
#include <thread>
class Cycler
{
private:
int startColor;
int endColor;
int current;
public:
Cycler(int start, int end) : startColor(start), endColor(end), current(start) {}
int next()
{
if (current >= endColor)
{
current = startColor;
}
return current++;
}
};
int main()
{
initscr(); // Initialize the window
start_color(); // Start color functionality
noecho(); // Do not echo any keypresses
curs_set(FALSE); // Do not display a cursor
int height, width;
getmaxyx(stdscr, height, width);
int RED = 1; // Reserve the red color at color ID 1
init_extended_color(RED, 1000, 0, 0); // Initialize the red color
Cycler colorCycler(2, COLORS - 1); // RED is reserved at 1, start at 2
Cycler pairCycler(1, COLOR_PAIRS - 1);
bool has_extended_support = has_colors() && can_change_color();
attr_on(COLOR_PAIR(1), NULL);
mvprintw(0, 0, "COLORS:%d COLOR_PAIRS:%d ExtendedSupport:%s", COLORS, COLOR_PAIRS, has_extended_support ? "True" : "False");
attr_off(COLOR_PAIR(1), NULL);
for (int y = 1; y < height - 1; ++y)
{
for (int x = 0; x < width; x += 5)
{
int color_id = colorCycler.next();
int pair_id = pairCycler.next();
int intensity = int((color_id / double(COLORS - 1)) * 1000);
init_extended_color(color_id, intensity, intensity, intensity);
// Create a new color pair, (RED) foreground, (color) background
init_extended_pair(pair_id, RED, color_id);
char str[6];
attr_on(COLOR_PAIR(pair_id), NULL);
mvprintw(y, x, "%5d", pair_id);
attr_off(COLOR_PAIR(pair_id), NULL);
}
}
refresh(); // Refresh the screen
getch(); // Wait for a keypress
endwin(); // End the window session
return 0;
}