如何在ncurses窗口循环中更新字符串?解决字符残留问题
NCurses窗口按键切换时字符串残留问题解决
问题描述
我需要编写一个程序,捕获用户的按键值并在ncurses窗口显示对应的字符串。用户未按下回车键时,可再次按下方向键,每次按键后字符串都会更新。但程序运行不符合预期:当按下右键再按下左键时,窗口会残留前一个字符串的部分内容。
原代码
#define _POSIX_C_SOURCE 200201L #include <stdlib.h> #include <curses.h> #include <time.h> int main () { srand(time(NULL)); initscr(); cbreak(); noecho(); // get screen sizes int yMax, xMax; getmaxyx(stdscr, yMax, xMax); //create a new window for input int height = 10; int width = 120; WINDOW * inputwin = newwin(height, width, yMax/2 - 5, (xMax/2 - width/2)); box(inputwin, 0, 0); refresh(); wrefresh(inputwin); // get amount rows echo(); wmove(inputwin, 4, width/2 - 38); wprintw(inputwin, "Press key left to choose beginner level, key right - intermediate, key up - advances."); int amount_rows = 0; keypad(inputwin, TRUE); while (true) { move(6, 50); // move to begining of line clrtoeol(); // clear line move(6, 50); // move back to where you were wrefresh(inputwin); int c = wgetch(inputwin); if (c == KEY_LEFT) { mvwprintw(inputwin, 6, 50, "You chose beginner"); amount_rows = 2; } else if (c == KEY_RIGHT) { mvwprintw(inputwin, 6, 50, "You chose intermediate"); amount_rows = 3; } else if (c == KEY_UP) { mvwprintw(inputwin, 6, 50, "You chose advanced"); amount_rows = 5; } else mvwprintw(inputwin, 6, 50, "INCORRECT INPUT. TRY AGAIN"); wrefresh(inputwin); mvwprintw(inputwin, 7, 47, "Press enter to continue"); int a = wgetch(inputwin); if (a == KEY_ENTER) break; wrefresh(inputwin); } // mvwprintw(inputwin, 7, 47, "Press enter to continue"); // int a = wgetch(inputwin); // // if (a == KEY_ENTER) { // // delwin(inputwin); // // } getch(); endwin(); return EXIT_SUCCESS; }
现象说明
按下右键时显示正常;切换左键后,窗口出现前一个字符串的残留部分。
问题原因
你当前使用的move()和clrtoeol()是针对**标准窗口stdscr**操作的,但提示文本输出在自定义窗口inputwin中,清空操作未作用在目标窗口上,导致较长的旧字符串(比如"intermediate")残留部分字符。
修复方案
将针对stdscr的操作替换为自定义窗口inputwin的专属操作:
- 用
wmove()替代move() - 用
wclrtoeol()替代clrtoeol() - 补充回车键的兼容性判断,同时处理
KEY_ENTER和'\n' - 切换按键时清空"Press enter to continue"行,避免内容重叠
修改后的循环代码
while (true) { wmove(inputwin, 6, 50); // 移动到自定义窗口的目标行位置 wclrtoeol(); // 清空该窗口当前位置到行尾的内容 wmove(inputwin, 6, 50); // 移回原位置 wrefresh(inputwin); int c = wgetch(inputwin); if (c == KEY_LEFT) { mvwprintw(inputwin, 6, 50, "You chose beginner"); amount_rows = 2; } else if (c == KEY_RIGHT) { mvwprintw(inputwin, 6, 50, "You chose intermediate"); amount_rows = 3; } else if (c == KEY_UP) { mvwprintw(inputwin, 6, 50, "You chose advanced"); amount_rows = 5; } else mvwprintw(inputwin, 6, 50, "INCORRECT INPUT. TRY AGAIN"); wrefresh(inputwin); mvwprintw(inputwin, 7, 47, "Press enter to continue"); int a = wgetch(inputwin); // 兼容不同系统的回车键判断 if (a == KEY_ENTER || a == '\n') break; // 清空提示行,避免切换按键时内容重叠 wmove(inputwin, 7, 47); wclrtoeol(); wrefresh(inputwin); }
内容的提问来源于stack exchange,提问作者Lina Iliashenko
相关产品推荐
相关产品推荐

