ncurses: printw() druckt ohne refresh() auf den stdscr.
-
Hallo,
warum druckt z.B.
printw("TEST");
den string "TEST" auch ohne den Aufruf
refresh();
in das Terminal? Mich verwirt das, weil auf http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/helloworld.html#DISSECTION
im Abschnitt 2.2.2. The mysterious refresh()
folgendes steht:[...] This brings us to that mysterious refresh(). Well, when we called printw the data is actually written to an imaginary window, which is not updated on the screen yet. The job of printw is to update a few flags and data structures and write the data to a buffer corresponding to stdscr. In order to show it on the screen, we need to call refresh() and tell the curses system to dump the contents on the screen.
The philosophy behind all this is to allow the programmer to do multiple updates on the imaginary screen or windows and do a refresh once all his screen update is done. refresh() checks the window and updates only the portion which has been changed. This improves performance and offers greater flexibility too. But, it is sometimes frustrating to beginners. A common mistake committed by beginners is to forget to call refresh() after they did some update through printw() class of functions. I still forget to add it sometimes
Dort steht das erst in den Puffer geschrieben wird. Erst mit dem Aufruf von refresh() wird auf den stdscr gedruckt. Bei mir funktioniert es aber auch ohne refresh() .
Meine Frage an Euch : Wo liegt mein Denkfehler?
-
Die Frage ist: Wie sieht dein Code aus? Wenn du das folgendermaßen testest, wird der Text "test" ausgegeben, obwohl kein
refresh()
aufgerufen wird:#include <ncurses.h> int main() { initscr(); printw("test"); getch(); endwin(); }
getch()
ruft nämlich internrefresh()
auf, bevor auf Input gewartet wird (steht zumindest in der man page).
-
Mein Code sieht folgendermaßen aus:
#include <ncurses.h> using namespace std; int main() { initscr(); noecho(); keypad(stdscr, TRUE); int height_y , wide_x; getmaxyx(stdscr, height_y, wide_x); int curr_y = height_y/2; int curr_x = wide_x/2; mvaddch(curr_y, curr_x, 'X'); char ch; while(ch = getch()){ switch(ch) { case 4: if(curr_x > 0){ mvaddch(curr_y, curr_x--, ' '); mvaddch(curr_y, curr_x, 'X'); mvprintw(0,0, " "); mvprintw(0,0, "curr_y %d curr_x %d", curr_y, curr_x); break; } else break; case 5: if(curr_x+1 < wide_x){ mvaddch(curr_y, curr_x++, ' '); mvaddch(curr_y, curr_x, 'X'); mvprintw(0,0, " "); mvprintw(0,0, "curr_y %d curr_x %d", curr_y, curr_x); break; } else break; case 2: if(curr_y+1 < height_y){ mvaddch(curr_y++, curr_x, ' '); mvaddch(curr_y, curr_x, 'X'); mvprintw(0,0, " "); mvprintw(0,0, "curr_y %d curr_x %d", curr_y, curr_x); break; } else break; case 3: if(curr_y > 0){ mvaddch(curr_y--, curr_x, ' '); mvaddch(curr_y, curr_x, 'X'); mvprintw(0,0, " "); mvprintw(0,0, "curr_y %d curr_x %d", curr_y, curr_x); break; } else break; } } endwin(); return 0; }
In meiner while Schleife ist ja ein getch drin. Das wirds wohl sein. Du meintest diese Seite? http://invisible-island.net/ncurses/man/curs_getch.3x.html
If the window is not a pad, and it has been moved or modi-
fied since the last call to wrefresh, wrefresh will be
called before another character is read.2 Fragen hätte ich noch...
Warum spuckt der compiler mir in Zeile 15 eine Warnung aus?/home/jo/Dokumente/ncurses_tutorial/my/ncurses3/main.cpp:16: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
Wenn ich meinen Code ein bischen verändere indem ich aus
case 4:
,
case KEY_LEFT
mache, kommt eine Warnung an der Stelle an der jetzt
case KEY_LEFT
steht.
/home/jo/Dokumente/ncurses_tutorial/my/ncurses3/main.cpp:19: warning: case label value exceeds maximum value for type [enabled by default]
Wenn ich im Programm dann die linke Pfeiltaste betätige, bewegt sich das Kreuz nicht mehr nach links.
Ich muss mal dazu sagen das ich mich erst seit 2 Tagen mit der Bibliothek ncurses beschäftige.
-
Genau, das
getch()
in der Schleife (Zeile 15) aktualisiert immer den screen. Du hast die richtige Stelle der man page zitiert.Zu deiner zweiten Frage:
Die Warnung kommt, weil der Compiler denkt das du statt „=“ in der while Bedingung „==“ gemeint haben könntest. Wenn du den Ausdruck erneut in Klammern setztwhile((ch = getch()))
sagst du dem Compiler dadurch, dass du weißt was du tust und die Warnung verschwindet.
Allerdings frage ich mich, was du duch diese Bedingung erreichen möchtest.getch
liefert den Wert der gedrückten Taste zurück oderERR
im Fehlerfall. Ich wüsste nicht wie ichgetch
dazu bringe 0 zurückzuliefern. Teste lieber aufwhile ((ch = getch()) != 'q')
oder sowas in der Art.
Die andere Warnung besagt, dass die Konstante
KEY_LEFT
nicht in deinench
passt. Das liegt daran, dassch
einchar
und keinint
ist, was es eigentlich sein müsste (siehe man page).
-
Ahhhh
Funktioniert alles.
Danke dir für deine Hilfe.