终端中的光标闪烁消除,如何?

Posted

技术标签:

【中文标题】终端中的光标闪烁消除,如何?【英文标题】:cursor blinking removal in terminal, how to? 【发布时间】:2012-06-11 21:00:59 【问题描述】:

我使用以下行在我的 c++ 程序中输出模拟的进度信息,

double N=0;
double percent=0;
double total = 1000000;
for (int i; i<total; ++i)

    percent = 100*i/total;
    printf("\r[%6.4f%%]",percent);

效果很好!

但问题是我看到终端光标一直在数字中循环闪烁,这很烦人,有人知道如何摆脱这个吗?

我见过一些程序,例如 wget 或 ubuntu apt,它们也使用进度条或百分比,但它们似乎没有光标闪烁的问题,我想知道它们是如何做到的?

谢谢!

【问题讨论】:

【参考方案1】:

您可以在DECSMDECRM 中使用DECTCEM(DEC 文本光标启用模式)模式隐藏和显示光标:

fputs("\e[?25l", stdout); /* hide the cursor */

fputs("\e[?25h", stdout); /* show the cursor */

【讨论】:

你的意思是在循环中,在这个命令之后printf("\r[%6.4f%%]",percent);? 无论在哪里需要。通常,您会在任何更新之前隐藏光标,执行所有更新,然后在最后再次显示它。如果您愿意,您甚至可以将它们全部合并到一个 printf 中。【参考方案2】:

只是猜测:尝试使用适当数量的“\b”(退格)字符而不是“\r”。

== 编辑 ==

我不是 Linux shell 向导,但这可能有用:

system("setterm -cursor off");
// ...display percentages...
system("setterm -cursor on");

别忘了#include &lt;cstdlib&gt;&lt;iostream&gt;

【讨论】:

为什么需要百分比?你可以一个接一个地写“#”字符。例如,每个新的 10%s 对应一个“#”。 哎呀,我喜欢数字 :) 好的,我会尝试 # 并让你知道结果,但无论如何,只是一个 google,有人说 wget 没有使用 ncurses 哎呀,好像关了就不能再开了 使用系统不好。 fork 之后执行的程序将执行此操作 ***.com/a/10995085/78712 。你这样可以吗? system("echo hello world!");【参考方案3】:

避免光标闪烁的一种方法是(按照建议)暂时隐藏光标。

但是,这只是解决方案的一部分。您的程序也应该考虑到这一点:

隐藏光标并修改屏幕后,之前再次显示光标移动回到原来的位置。 隐藏/显示光标只会在您的更新只花费少量时间时使光标不会明显闪烁。如果您碰巧将此与一些耗时的过程混合在一起,您的光标闪烁。

使用setterm 的建议解决方案不可移植;它特定于 Linux 控制台。并且使用system 运行可执行文件并不是真正必要的。但即使是跑步

system("tput civis");
...
system("tput cnorm");

是对使用 setterm 的改进。

检查wget 的源代码没有发现任何隐藏光标的转义序列。您在进度条中看到的是,每当它执行一些耗时的操作时,它会将光标留在大致相同的位置。到终端的输出只需要很少的时间,以至于您不会注意到该行的瞬时重写(通过打印回车,然后重新写入大部分行)。如果速度较慢,那么隐藏光标会有所帮助——在一定程度上。

顺便说一句,这种光标隐藏技术在某些编辑器(vim 和 vile)的终端驱动程序中使用。

【讨论】:

我认为wget没有这个问题的真正原因是因为它们打印到没有缓冲的stderr,而不是缓冲的stdout【参考方案4】:

那些应用程序可能正在使用ncurses。见mvaddstr

【讨论】:

wget 和 fbi 是两个不使用 ncurses 但能够完全隐藏光标的程序示例。【参考方案5】:

光标跳来跳去的原因是因为stdout 被缓冲了,所以你实际上不知道在某个时间点打印了多少个字符。 wget 没有跳跃光标的原因是它们实际上是打印到 stderr 而不是无缓冲的。请尝试以下操作:

fprintf(stderr, "\r[%6.4f%%]", percent);

如果您使用管道将其余输出保存在某处,这还有一个优点,即不会弄乱文件:

$ ./executable > log.data

【讨论】:

【参考方案6】:

按插入键...如果不起作用,请按键盘上的 fn 键。 这肯定会工作 希望这会有所帮助

【讨论】:

以上是关于终端中的光标闪烁消除,如何?的主要内容,如果未能解决你的问题,请参考以下文章

如何消除此 JQuery/CSS3 动画中的闪烁

禁用 UITextField 中的闪烁光标?

加载颤振时消除图像中的白色闪烁

如何在bash shell中设置光标颜色[重复]

am5718:Linux中如何去掉LCD上闪烁的光标

jquery 虚拟键盘 - Chrome 和 Edge 中的光标不闪烁