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 intern refresh() 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 setzt

    while((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 oder ERR im Fehlerfall. Ich wüsste nicht wie ich getch dazu bringe 0 zurückzuliefern. Teste lieber auf

    while ((ch = getch()) != 'q')
    

    oder sowas in der Art.

    Die andere Warnung besagt, dass die Konstante KEY_LEFT nicht in deinen ch passt. Das liegt daran, dass ch ein char und kein int ist, was es eigentlich sein müsste (siehe man page).



  • Ahhhh 🙂
    Funktioniert alles.
    Danke dir für deine Hilfe.


Anmelden zum Antworten