Основное меню Ncurses
Я пытаюсь сделать основное меню на C. Я должен сделать это с помощью ncurses lib. Я работал с этим уроком: видео на YouTube
Но у моей версии есть некоторые проблемы: 1) Меню не будет печататься должным образом, оно будет отображаться только при выборе пунктов меню. Тогда подсветка не исчезнет 2) Опция, сделанная в меню, не будет напечатана сверху
Вы можете мне помочь? Это идея меню хорошо или я должен искать другой учебник (любая помощь?).
#include <stdio.h>
#include <ncurses.h>
#include <string.h>
#include <menu.h>
int main(int argc, char **argv)
{
int i, c;
char powitanie[]="SLOWNIK UNIWERSALNY";
int szer, dlug; //wartosci dlugosci i szerokosci terminalu
initscr(); //Inizjalizacja całości ncurses, kolory itp
raw();
noecho();
keypad(stdscr, TRUE);
start_color();
//init_pair(1, COLOR_BLUE, COLOR_BLACK); //wybór kolorów
getmaxyx(stdscr, szer, dlug); //pobranie rozmiarów terminalu
move(szer/2, (dlug-strlen(powitanie))/2); //przesuwamy kursor na środek (tak aby się ładnie wydrukowało)
//attron(COLOR_PAIR(1)); //Aktywujemy wybrane kolory
printw(powitanie); //Drukujemy powitanie
//attroff(COLOR_PAIR(1));//Dezaktywujemy kolory
refresh();//Odswiezamy (inaczej się nie wyswietli)
WINDOW * menuwin=newwin(6, dlug-12, szer-8, 6); //Definiujemy i tworzymy 'okno'
box(menuwin, 0, 0);
refresh();//ponownie odświeżamy aby okno się pojawiło
wrefresh(menuwin);//odświeżamy samo okno
keypad(menuwin, TRUE);//umozliwiamy dzialanie klawiatury w oknie
char *opcje[] = {
"Tlumacz z Polskiego na Angielski",
"Tlumacz z Angielskiego na Polski",
"Edystuj slownik",
"Wybierz slownik",
"Wyjdz",
};
int wybor;
int zaznacz=0;
while(1)//cala ta petla sluzy ciaglemu tworzeniu menu z podswietleniem wybranego elementu
{
for(i=0; i<5; i++)
{
if(i==zaznacz)
{
wattron(menuwin, A_REVERSE);
mvwprintw(menuwin, i+1, 1, opcje[i]);
wattroff(menuwin, A_REVERSE);
}
wybor = wgetch(menuwin);
switch(wybor)
{
case KEY_UP:
zaznacz--;
if(zaznacz==-1) zaznacz=0;//zabezpieczenie przed wyjsciem "poza" menu
break;
case KEY_DOWN:
zaznacz++;
if(zaznacz==5) zaznacz=4;
break;
default:
break;
}
if(wybor==10) break;
}
printw("Wybrano:%s", opcje[zaznacz]);
}
return(0);
}
PS: комментарии к коду не на английском языке, но я надеюсь, что они не понадобятся
1 ответ
Здесь довольно много проблем. Я включил измененную версию вашего кода, которая работает, и я постараюсь описать изменения.
Были некоторые неиспользованные переменные, а именно argc
, argv
, а также c
Я бросил это void
чтобы заставить замолчать предупреждения компилятора. Вы можете удалить c
и изменить на int main(void)
, если хотите, вообще удалите эти переменные.
Я добавил stdlib.h
заголовочный файл к вашему #include
с для exit()
функция. Это используется в новой функции ошибки, fail()
, что я добавил в ваш код. Вы всегда должны проверять возвращаемые значения любой функции, которую вы вызываете при программировании на C. Здесь особенно важно проверить, во-первых, поддерживает ли терминал цвет с помощью has_colors()
функция, а затем, если вызов start_color()
успешно. Если один из них не сработает, fail()
функция вызывается с сообщением об ошибке, и программа завершается с EXIT_FAILURE
значение. Функция has_colors()
возвращает bool
и start_color()
функция возвращает int
(OK
в случае успеха, в противном случае ERR
).
Теперь, когда цвета были инициализированы, я вижу, что нижняя граница вашего окна выбора меню перезаписывается текстом меню. Чтобы это исправить, я изменил размер вашего окна, сделав его на одну строку выше:
WINDOW * menuwin=newwin(7, dlug-12, szer-9, 6);
Основная проблема неправильной печати, о которой вы сообщили, была из-за неуместной скобки в for
Цикл управления печатью пунктов меню. Я воспользовался возможностью немного реорганизовать цикл; теперь есть только один звонок mvwprintw()
, A_REVERSE
Атрибут устанавливается перед печатью, если текущий элемент также является выбранным элементом, и он снова сбрасывается после печати.
Я также изменил предельные тесты в switch
утверждение из равенства в неравенства. Лучше использовать, например, if (zaznacz < 0)
вместо if (zaznacz == -1)
в таких случаях. Я добавил символ новой строки в начало строки формата в финале printw()
, поскольку некоторые из вариантов выбора слишком длинные, чтобы поместиться в окне в конце заголовка. Вы можете перемещать этот вывод куда угодно.
Наконец, я добавил refresh()
после финала printw()
заявление и getch()
ждать, пока пользователь нажмет ENTER, прежде чем выйти из программы. Это очень важно, чтобы очистить, позвонив endwin()
перед выходом из программы NCurses. Эта функция отменяет изменения, внесенные в ваш терминал с помощью NCurses во время работы вашей программы, и невозможность сделать это может привести к неприятностям терминала.
#include <stdio.h>
#include <ncurses.h>
#include <string.h>
#include <menu.h>
#include <stdlib.h> // added for exit() function
void fail(char *msg) {
endwin();
puts(msg);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
/* Commandline argument currently unused */
(void) argc;
(void) argv;
int i, c;
(void) c; // c is currently unused
char powitanie[]="SLOWNIK UNIWERSALNY";
int szer, dlug; //wartosci dlugosci i szerokosci terminalu
initscr(); //Inizjalizacja całości ncurses, kolory itp
raw();
noecho();
keypad(stdscr, TRUE);
/* Test to see if terminal has colors */
if (has_colors() == false) {
fail("Colors unavailable\n");
}
if (start_color() != OK) {
fail("Unable to start colors\n");
}
//init_pair(1, COLOR_BLUE, COLOR_BLACK); //wybór kolorów
getmaxyx(stdscr, szer, dlug); //pobranie rozmiarów terminalu
move(szer/2, (dlug-strlen(powitanie))/2); //przesuwamy kursor na środek (tak aby się ładnie wydrukowało)
//attron(COLOR_PAIR(1)); //Aktywujemy wybrane kolory
printw(powitanie); //Drukujemy powitanie
//attroff(COLOR_PAIR(1));//Dezaktywujemy kolory
refresh();//Odswiezamy (inaczej się nie wyswietli)
WINDOW * menuwin=newwin(7, dlug-12, szer-9, 6); //Definiujemy i tworzymy 'okno'
box(menuwin, 0, 0);
refresh();//ponownie odświeżamy aby okno się pojawiło
wrefresh(menuwin);//odświeżamy samo okno
keypad(menuwin, TRUE);//umozliwiamy dzialanie klawiatury w oknie
char *opcje[] = {
"Tlumacz z Polskiego na Angielski",
"Tlumacz z Angielskiego na Polski",
"Edystuj slownik",
"Wybierz slownik",
"Wyjdz",
};
int wybor;
int zaznacz=0;
while(1)//cala ta petla sluzy ciaglemu tworzeniu menu z podswietleniem wybranego elementu
{
for(i = 0; i < 5; i++) {
if(i == zaznacz)
wattron(menuwin, A_REVERSE);
mvwprintw(menuwin, i+1, 1, opcje[i]);
if (i == zaznacz)
wattroff(menuwin, A_REVERSE);
}
wybor = wgetch(menuwin);
switch(wybor)
{
case KEY_UP:
zaznacz--;
if(zaznacz < 0) zaznacz = 0;//zabezpieczenie przed wyjsciem "poza" menu
break;
case KEY_DOWN:
zaznacz++;
if(zaznacz > 4) zaznacz = 4;
break;
default:
break;
}
if(wybor==10) break;
}
printw("\nWybrano:%s", opcje[zaznacz]);
refresh();
/* Wait for user to press enter to exit */
getch();
/* Need to cleanup before exit */
endwin();
return 0;
}