Python curses.flash() 仅在特定条件下工作,但这些似乎没有记录在案



在使用python诅咒编程时,我遇到了许多不可预测的行为,我将不在这里讨论。但是现在,在这些问题中有一个特别的问题困扰着我,理解它可能有助于解决其他问题。

只要我不调用stdscr.getkey()。事实上,屏幕每隔半秒就会闪烁一次。如果我调用stdscr。getkey()屏幕闪一次且仅闪一次。按下一个键并进入循环并不会改变任何东西。为什么?我没有找到任何关于flash()和getkey()的文档,可以解释发生了什么。

#! /usr/bin/env python3
import curses
def test(stdscr):
import time
curses.noecho()
curses.cbreak()
curses.curs_set(0)
stdscr.keypad(True)

while True:
curses.flash()
time.sleep(0.5)
# ~ stdscr.getkey()

curses.wrapper(test)

也许一些诅咒功能改变了一些状态,使flash不再工作?但是怎么做,为什么呢?

flash在curses中使用终端描述中的flash能力。例如,使用infocmp,您可能会在输出中看到这样的内容:

flash=E[?5h$<100/>E?5l,

告诉应用程序发送一个转义序列,等待100毫秒,然后发送另一个转义序列。(不是所有的"xter"想要实现DECSCNM;该缺陷通常在终端数据库注释中注明);

诅咒中的所有屏幕更新都被缓冲;flash是一个更新。您可以使用refresh显式地将该缓冲区刷新到终端,或者依赖于读取输入的函数(作为副作用,它将执行refresh)。如果你的程序被阻止写入终端,你将看不到闪烁。

无论调用getch还是getkey,通常都会阻塞直到你按下一个键。您可以使用timeout、nodelay等,这些在文档中有提到。

顺便说一下,time.sleep会干扰刷新。使用napms

. 例如:

> diff -u foo.orig foo
--- foo.orig    2022-07-20 03:53:05.000000000 -0400
+++ foo 2022-07-20 03:56:18.833794715 -0400
@@ -8,10 +8,14 @@
curses.cbreak()
curses.curs_set(0)
stdscr.keypad(True)
-    
+    stdscr.nodelay(1)
+
while True:
curses.flash()
-        time.sleep(0.5)
-        # ~ stdscr.getkey()
-        
+        curses.napms(500)
+        try:
+            stdscr.getkey()
+        except curses.error:
+            pass
+
curses.wrapper(test)

进一步阅读:

  • Curses Programming with Python
  • 哔哔声,闪光-诅咒铃声和屏幕闪光例程
  • 读取字符(getch)

OP注释调用use_default_colors有助于flash。这取决于终端(就像DECSCNM一样),但它会产生差异的原因是因为python诅咒包装器调用start_color,这会导致ncurses尝试将终端涂成黑白。调用use_default_colors在一定程度上取消了这一点,因为脚本中没有使用显式的颜色,因此您将只看到终端的默认颜色。如果终端仿真器仅在使用默认(未着色)配置时显示DECSCNM,那么这就是您将获得的"工作"。flash .

就护士而言,"flash"与colorrefresh的详细信息是分开的(参见源代码)。它只依赖于刷新时完成的缓冲区刷新。

好的,所以它可能不是完美的,但我相信我遇到了一些看起来像一个可能的解决方案。

通过在多个终端模拟器上测试代码片段,如支持透明的终止器,我注意到调用refresh()或getkey()会用新颜色擦除背景。

当它发生时,flash()不再操作。我不确定为什么会发生这种情况(即,为什么refresh(), getch()和getkey()改变颜色设置),但我们在这里。

所以一个工作和可移植的代码(假设visual bell是启用的)看起来像这样:

#! /usr/bin/env python3
import curses
def test(stdscr):
curses.noecho()
curses.cbreak()
curses.curs_set(0)
stdscr.keypad(True)
stdscr.nodelay(1)
curses.use_default_colors()
while True:
curses.flash()
curses.napms(500)
try:
stdscr.getkey()
break
except curses.error:
pass

curses.wrapper(test)

curses.use_default_colors()

欢迎进一步解释!

编辑:查看Thomas Dickey的回答了解更多细节

相关内容

  • 没有找到相关文章

最新更新