[英]changes not showing in field in ncurses
我有一個 ncurses 程序,它是一個登錄菜單,我使用字段作為用戶名和密碼。
問題是當我在字段中輸入內容時,字符會注冊但不會顯示在終端中。 換句話說,如果您執行代碼並輸入一些內容,您將無法在終端中看到它,但是如果您按 F2,您可以看到字符已注冊。
這是我的代碼:
測試.cpp
#include <curses.h>
#include <form.h>
#include <menu.h>
#include <string>
#include <cstring>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
class WelcomeMenu {
private:
int _row; // number of rows of the terminal
int _col; // number of columns of the terminal
public:
WelcomeMenu();
~WelcomeMenu();
void welcomeBox();
void loginMenu();
void registerMenu();
};
WelcomeMenu::WelcomeMenu(){
initscr();
noecho();
cbreak();
keypad(stdscr, true);
int row, col;
getmaxyx(stdscr,row,col); /* get the number of rows and columns */
this->_row = row; this->_col = col;
loginMenu();
}
WelcomeMenu::~WelcomeMenu(){
refresh();
endwin();
}
/*
* This is useful because ncurses fill fields blanks with spaces.
*/
char* trim_whitespaces(char *str)
{
char *end;
// trim leading space
while(isspace(*str))
str++;
if(*str == 0) // all spaces?
return str;
// trim trailing space
end = str + strnlen(str, 128) - 1;
while(end > str && isspace(*end))
end--;
// write new null terminator
*(end+1) = '\0';
return str;
}
void WelcomeMenu::loginMenu(){
// erase();
FORM *form;
FIELD *fields[5];
WINDOW *win_body, *win_form;
int ch;
win_body = newwin(24, 80, 0, 0);
assert(win_body != NULL);
box(win_body, 0, 0);
win_form = derwin(win_body, 20, 78, 3, 1);
assert(win_form != NULL);
box(win_form, 0, 0);
mvwprintw(win_body, 1, 2, "Press F1 to quit and F2 to print fields content");
fields[0] = new_field(1, 10, 0, 0, 0, 0);
fields[1] = new_field(1, 40, 0, 15, 0, 0);
fields[2] = new_field(1, 10, 2, 0, 0, 0);
fields[3] = new_field(1, 40, 2, 15, 0, 0);
fields[4] = NULL;
assert(fields[0] != NULL && fields[1] != NULL && fields[2] != NULL && fields[3] != NULL);
set_field_buffer(fields[0], 0, "Username: ");
set_field_buffer(fields[1], 0, "username");
set_field_buffer(fields[2], 0, "Password: ");
set_field_buffer(fields[3], 0, "password");
set_field_opts(fields[0], O_VISIBLE | O_PUBLIC | O_AUTOSKIP);
set_field_opts(fields[1], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE);
set_field_opts(fields[2], O_VISIBLE | O_PUBLIC | O_AUTOSKIP);
set_field_opts(fields[3], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE);
set_field_back(fields[1], A_UNDERLINE);
set_field_back(fields[3], A_UNDERLINE);
form = new_form(fields);
assert(form != NULL);
set_form_win(form, win_form);
set_form_sub(form, derwin(win_form, 18, 76, 1, 1));
post_form(form);
refresh();
wrefresh(win_body);
wrefresh(win_form);
while ((ch = getch()) != KEY_F(1)){
switch (ch) {
case KEY_F(2):
// Or the current field buffer won't be sync with what is displayed
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
move(LINES-3, 2);
for (int i = 0; fields[i]; i++) {
printw("%s", trim_whitespaces(field_buffer(fields[i], 0)));
if (field_opts(fields[i]) & O_ACTIVE)
printw("\"\t");
else
printw(": \"");
}
refresh();
pos_form_cursor(form);
break;
case KEY_DOWN:
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_END_LINE);
break;
case KEY_UP:
form_driver(form, REQ_PREV_FIELD);
form_driver(form, REQ_END_LINE);
break;
case KEY_LEFT:
form_driver(form, REQ_PREV_CHAR);
break;
case KEY_RIGHT:
form_driver(form, REQ_NEXT_CHAR);
break;
// Delete the char before cursor
case KEY_BACKSPACE:
case 127:
form_driver(form, REQ_DEL_PREV);
break;
// Delete the char under the cursor
case KEY_DC:
form_driver(form, REQ_DEL_CHAR);
break;
default:
form_driver(form, ch);
break;
}
}
wrefresh(win_form);
unpost_form(form);
free_form(form);
free_field(fields[0]);
free_field(fields[1]);
free_field(fields[2]);
free_field(fields[3]);
delwin(win_form);
delwin(win_body);
}
int main(){
WelcomeMenu * myConWin = new WelcomeMenu();
delete myConWin;
return 0;
}
你可以像這樣編譯它: g++ -lncurses -lform test.cpp
預先感謝您的回復
您需要使用echo
和noecho
打開/關閉回聲。 如果您願意,可以將該部分烘焙到輸入函數中:
#include <memory>
struct input_context {
input_context() {
echo(); // echo typed characters
curs_set(1); // show the cursor
}
~input_context() {
curs_set(0); // hide the cursor
noecho(); // turn off echoing
}
};
std::string get_string(WINDOW* win, size_t len) {
std::unique_ptr<char[]> buf = std::make_unique<char[]>(len);
input_context dummy;
if(wgetnstr(win, buf.get(), len) != ERR) return std::string{buf.get()};
return {};
}
注意 1:當所有其他選項都已耗盡時,您應該只使用new
/ delete
(和new[]
/ delete[]
)。 在您的main
,您可以使用自動變量替換WelcomeMenu
的動態創建:
int main(){
WelcomeMenu myConWin;
}
注 2:使用nullptr
,而不是NULL
。
fields[4] = nullptr; // was NULL
注 3:如@kebs 在評論中所述,您應該使用 C++ 版本的頭文件:
#include <cassert> // was assert.h
#include <cstdio> // was stdio.h
#include <cstdlib> // was stdlib.h
該示例的基本問題是它沒有提供顯示字符的功能。 在 ncurses 中,這將使用form_driver
函數完成:
form_driver
Once a form has been posted (displayed), you should funnel input events
to it through form_driver. This routine has three major input cases:
o The input is a form navigation request. Navigation request codes
are constants defined in <form.h>, which are distinct from the key-
and character codes returned by wgetch(3x).
o The input is a printable character. Printable characters (which
must be positive, less than 256) are checked according to the pro-
gram's locale settings.
o The input is the KEY_MOUSE special key associated with an mouse
event.
讓你的程序使用form_driver
需要對程序進行一些重組,將 switch 語句移動到一個可以從表單驅動程序調用的函數中。
ncurses 示例包括一些使用form_driver
。 您可能想通讀測試代碼,了解基本循環如何
while (!finished) { switch (form_driver(form, c = form_virtualize(form, w))) { case E_OK: MvAddStr(5, 57, field_buffer(secure, 1)); clrtoeol(); refresh(); break; case E_UNKNOWN_COMMAND: finished = my_form_driver(form, c); break; default: beep(); break; }
使用它的form_virtualize
函數來讀取字符(或表單請求)。 您(未)看到的可打印字符由form_driver
處理,它更新表單上的當前字段。 您可以像在form_virtualize
那樣操作字段緩沖區並執行其他特殊操作,但是更新表單中的字段是您使用form_driver
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.