Ncurses 将光标放在正确的面板中

Ncurses place cursor in correct panel

我正在制作一个包含多个 windows 的应用程序,每个都包含在一个面板内。其中之一 windows 尤其必须从键盘获取输入。我还需要能够检测特殊键,例如 F 键和箭头键。我当前的应用程序正在执行此操作。但是,即使在我调用 wmove(my_wins[1], 3, 2).

之后,光标也不在正确的位置

如何将光标移动到正确面板中的正确位置?我希望终端光标位于我的第二个 window (my_wins[1]) 中,在我想从中获取字符的下一个空 space 中。在本例中,这是 my_wins[1] 中输入最后一个字符后的第 3 行。

我的代码:

#include <panel.h>
#include <ncurses.h>
#include <string>
#include <stdlib.h>
#include <unistd.h>
#include <vector>

WINDOW *my_wins[4];
PANEL* my_panels[4];

// forward declarations
void make_screen();
void clear_win1();
void get_input();

int main()
{
    initscr();
    cbreak();
    noecho();

    make_screen();
    get_input();
    endwin();
}

void get_input()
{   
    // enable f-keys and arrow keys
    keypad(my_wins[1], TRUE);

    int ch;
    std::string str = "";
    std::vector<std::string> cmds;

    while ((ch = wgetch(my_wins[1])) != KEY_F(1))
    {   
        switch(ch)
        {   
            case 127: // delete
                if (str.size() > 0)
                {   
                    str.erase(str.size()-1);
                }
                break;
            case '\n':
                cmds.push_back(str);
                str = "";
                break;
            default:
                if (ch >= ' ' || ch <= 126)
                {   
                    str += (char) ch;
                }
                break;
        }
        clear_win1();
        mvwprintw(my_wins[1], 3, 2, "%s", str.c_str());
        wmove(my_wins[1], 3, 2+str.size()); 
        update_panels();
        doupdate();
    }
}

void make_screen()
{
    int maxx, maxy;
    getmaxyx(stdscr, maxy, maxx);

    float win1y = maxy;
    float win1x = (2.0/7)*maxx;

    float win2y = (3.0/5)*maxy;
    float win2x = (3.0/7)*maxx;

    float win3y = (3.0/5)*maxy; 
    float win3x = (2.0/7)*maxx;

    float win4y = (2.0/5)*maxy + 1;  
    float win4x = (5.0/7)*maxx;

    my_wins[0] = newwin(win1y, win1x, 0, 0); 
    my_wins[1] = newwin(win2y, win2x, 0, win1x);
    my_wins[2] = newwin(win3y, win3x, 0, win1x+win2x);
    my_wins[3] = newwin(win4y, win4x, win2y, win1x);

    /*  
     * Create borders around the windows so that you can see the effect
     * of panels
     */
    for(int i = 0; i < 4; ++i)
    {   
        box(my_wins[i], 0, 0); 
    }   

    my_panels[0] = new_panel(my_wins[0]);
    my_panels[1] = new_panel(my_wins[1]);
    my_panels[2] = new_panel(my_wins[2]);
    my_panels[3] = new_panel(my_wins[3]);

    mvwprintw(my_wins[0], 2, 2, "Yelp data");
    mvwprintw(my_wins[1], 2, 2, "I/O Window");
    mvwprintw(my_wins[2], 2, 2, "Menu items");
    mvwprintw(my_wins[3], 2, 2, "Tables");
    mvwprintw(my_wins[3], 3, 2, "maxy: %d, maxx: %d", maxy, maxx);
    mvwprintw(my_wins[3], 4, 2, "win1y: %f, win1x: %f", win1y, win1x);
    mvwprintw(my_wins[3], 5, 2, "win2y: %f, win2x: %f", win2y, win2x);
    mvwprintw(my_wins[3], 6, 2, "win3y: %f, win3x: %f", win3y, win3x);
    mvwprintw(my_wins[3], 7, 2, "win4y: %f, win4x: %f", win4y, win4x);
    mvwprintw(my_wins[1], 3, 2, "");

    update_panels();

    doupdate();
}

void clear_win1()
{
    werase(my_wins[1]);
    box(my_wins[1], 0, 0); 
    mvwprintw(my_wins[1], 2, 2, "I/O Window");
    update_panels();
    doupdate();
}

您的示例将 wmove 放在屏幕更新之前。这些更新将光标留在任何有意义的位置,以便在更新屏幕时将光标移动最小化。

此更改显示了如何执行您要求的操作:

$ diff -u foo.c.orig foo.c
--- foo.c.orig  2017-03-06 18:56:26.000000000 -0500
+++ foo.c       2017-03-06 19:00:03.568868347 -0500
@@ -33,6 +33,7 @@
     std::string str = "";
     std::vector<std::string> cmds;

+    wmove(my_wins[1], 3, 2+str.size()); 
     while ((ch = wgetch(my_wins[1])) != KEY_F(1))
     {   
         switch(ch)
@@ -56,9 +57,9 @@
         }
         clear_win1();
         mvwprintw(my_wins[1], 3, 2, "%s", str.c_str());
-        wmove(my_wins[1], 3, 2+str.size()); 
         update_panels();
         doupdate();
+        wmove(my_wins[1], 3, 2+str.size()); 
     }
 }