c++ - C ++,ncurses:在按下键之前无法显示菜单
问题描述
我和一个朋友正在终端内开发类似俄罗斯方块的游戏。我们使用 ncurses 来管理它,我们有不同的“观点”。例如,一个视图管理网格,而另一个视图管理菜单。但是我们有一个问题:当我们开始游戏时,我们需要按一个键才能看到它,否则窗口是空的。
这是我们创建菜单(构造函数)时运行的代码:
MenuScreen::MenuScreen()
{
if (has_colors())
{
use_default_colors();
start_color();
init_pair(WHITEONRED, COLOR_WHITE, COLOR_RED);
init_pair(WHITEONBLUE, COLOR_WHITE, COLOR_BLUE);
init_pair(REDONWHITE, COLOR_RED, COLOR_WHITE);
}
char *choices[] = /* The menu choices */
{
(char *)" Solo ",
(char *)" Bot ",
(char *)" Tetrix ",
(char *)" Quitter ",
NULL};
/* Calculate nchoices */
for (n_choices = 0; choices[n_choices]; n_choices++)
;
/* alloction of an iteam array for the menu */
my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
for (ssChoice = 0; ssChoice < n_choices; ++ssChoice)
my_items[ssChoice] = new_item(choices[ssChoice], NULL);
my_items[n_choices] = (ITEM *)NULL;
/* menu structure creation */
my_menu = new_menu((ITEM **)my_items);
/* symbole on the left of selected iteam*/
set_menu_mark(my_menu, "> ");
/* Windows Border cration */
wBorder = newwin(8, 40, LINES / 2 - 8 / 2, COLS / 2 - 40 / 2);
registerWindow(wBorder);
wattrset(wBorder, COLOR_PAIR(WHITEONRED));
windowsFilling(wBorder);
box(wBorder, 0, 0);
windowsBorderTitle(wBorder, " option ");
wUI = derwin(wBorder, 8 - 2, 40 - 2, 2, 2);
registerWindow(wUI);
set_menu_sub(my_menu, wUI);
set_menu_fore(my_menu, COLOR_PAIR(REDONWHITE));
set_menu_back(my_menu, COLOR_PAIR(WHITEONRED));
/* menu display */
post_menu(my_menu);
}
当按下下一个键时:
void MenuScreen::next()
{
menu_driver(my_menu, REQ_DOWN_ITEM);
update();
}
这是 update() 包含的内容:
void MenuScreen::update()
{
touchwin(wUI);
wrefresh(wUI);
touchwin(wBorder);
wrefresh(wBorder);
}
如果我们update()
从next()
函数中删除,当我们按下下一个键时菜单不再显示,所以我们尝试update()
在构造函数的末尾添加一个调用,但这不起作用。我们不知道是什么导致了这个错误。这是我们的完整源代码:
https ://github.com/Th0rgal/poyuterm/tree/22e2422930a29fbe83414e382fd566c3eac69366
编辑:这是我朋友制作的最小可重复示例:
要构建它,请将其复制粘贴到 menu.cpp 文件中并键入:g++ menu.cpp -o menu -lncurses -l menu
#include <stdlib.h> /* calloc() */
#include <string.h> /* strlen() */
#include <ncurses.h>
#include <menu.h>
#include <curses.h>
#define WHITEONRED 10
#define WHITEONBLUE 20
#define WHITEONBLACK 30
#define BLACKONWHITE 40
#define REDONWHITE 50
void windowsBorderTitle(WINDOW *pwin, const char *title)
{
int x, maxy, maxx, stringsize;
getmaxyx(pwin, maxy, maxx);
stringsize = 4 + strlen(title);
x = (maxx - stringsize) / 2;
mvwaddch(pwin, 0, x, ACS_RTEE);
waddch(pwin, ' ');
waddstr(pwin, title);
waddch(pwin, ' ');
waddch(pwin, ACS_LTEE);
}
void windowsFilling(WINDOW *pwin)
{
int y, x, maxy, maxx;
getmaxyx(pwin, maxy, maxx);
for (y = 0; y < maxy; y++)
for (x = 0; x < maxx; x++)
mvwaddch(pwin, y, x, ' ');
}
int main(int argc, char const *argv[])
{
initscr(); /* start ncurses */
cbreak(); /* immediately acquire each keystroke */
noecho(); /* do not echo user keystrokes */
keypad(stdscr, TRUE); /* enable detection of function keys */
int c;
ITEM **my_items;
MENU *my_menu;
WINDOW *wUI;
WINDOW *wBorder;
int n_choices;
int ssChoice;
int my_choice = -1;
if (has_colors())
{
use_default_colors();
start_color();
init_pair(WHITEONRED, COLOR_WHITE, COLOR_RED);
init_pair(WHITEONBLUE, COLOR_WHITE, COLOR_BLUE);
init_pair(REDONWHITE, COLOR_RED, COLOR_WHITE);
}
char *choices[] = /* The menu choices */
{
(char *)" Solo ",
(char *)" Bot ",
(char *)" Tetrix ",
(char *)" Quitter ",
NULL};
for(n_choices=0; choices[n_choices]; n_choices++);
/* ALLOCATE ITEM ARRAY AND INDIVIDUAL ITEMS */
my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
for(ssChoice = 0; ssChoice < n_choices; ++ssChoice)
my_items[ssChoice] = new_item(choices[ssChoice], NULL);
my_items[n_choices] = (ITEM *)NULL;
/* CREATE THE MENU STRUCTURE */
my_menu = new_menu((ITEM **)my_items);
/* PUT > TO THE LEFT OF HIGHLIGHTED ITEM */
set_menu_mark(my_menu, "> ");
/* SET UP WINDOW FOR MENU'S BORDER */
wBorder = newwin(16, 40, 2, 20);
wattrset(wBorder, COLOR_PAIR(WHITEONRED) | WA_BOLD);
windowsFilling(wBorder);
box(wBorder, 0, 0);
windowsBorderTitle(wBorder, "Choose one");
/* SET UP WINDOW FOR THE MENU'S USER INTERFACE */
wUI = derwin(wBorder, 16-2, 40-2, 2, 2);
/* ASSOCIATE THESE WINDOWS WITH THE MENU */
set_menu_win(my_menu, wBorder);
set_menu_sub(my_menu, wUI);
/* MATCH MENU'S COLORS TO THAT OF ITS WINDOWS */
set_menu_fore(my_menu, COLOR_PAIR(REDONWHITE));
set_menu_back(my_menu, COLOR_PAIR(WHITEONRED) | WA_BOLD);
/* SET UP AN ENVIRONMENT CONDUCIVE TO MENUING */
keypad(wUI, TRUE); /* enable detection of function keys */
noecho(); /* user keystrokes don't echo */
curs_set(0); /* make cursor invisible */
/* DISPLAY THE MENU */
post_menu(my_menu);
touchwin(wBorder);
wrefresh(wBorder);
while(my_choice == -1)
{
touchwin(wBorder);
wrefresh(wBorder);
touchwin(wUI); /* refresh prior to getch() */
wrefresh(wUI); /* refresh prior to getch() */
c = getch();
switch(c)
{
case KEY_DOWN:
menu_driver(my_menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(my_menu, REQ_UP_ITEM);
break;
case 10: /* Enter */
my_choice = item_index(current_item(my_menu));
pos_menu_cursor(my_menu);
break;
}
}
unpost_menu(my_menu);
for(ssChoice = 0; ssChoice < n_choices; ++ssChoice)
free_item(my_items[ssChoice]);
free_menu(my_menu);
delwin(wUI);
delwin(wBorder);
touchwin(stdscr);
wrefresh(stdscr);
endwin();
}
解决方案
推荐阅读
- terraform - 使用数据源时的 terraform 在给定后端中未找到给定工作空间的存储状态
- python - torch.cat 怎么可能只有一个张量?
- javascript - Uncaught TypeError: e is null after using a new component and modify its Onchange function
- python - 如何在 django 中使用整数和 ManytoMany 字段
- visual-studio - Add-PnPPage:找不到方法:'System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1
Enumerator.MoveNextAsync()' - three.js - 如何在three.js中正确配置scene.environment
- flask - gcloud 部署失败“应用程序中的错误:/ [POST] 上的异常”
- javascript - JavaScript index.js .babelrc 错误“不要克隆评论...
... } 无法克隆” - c++ - poco 切换到 MT 链接错误 Visual Studio 2019
- google-sheets - Google 表格 ImportXML 返回“未找到 URL 处的资源”错误