【问题标题】:Move a cursor inside a window - ncurses在窗口内移动光标 - ncurses
【发布时间】:2015-04-02 11:52:29
【问题描述】:

我使用 ncurse 创建了一个窗口,我试图能够在窗口内使用箭头键移动光标,并且只能在窗口内移动。据我了解,我必须使用wmove(),但显然我不知道如何使用它。

这里有一些代码 sn-ps 让你知道我做了什么:

int main(int argc, char **argv)
{
  WINDOW *my_win;
  int startx, starty, width, height;
  int ch;
  int x = 50;
  int y = 5;

  initscr();
  cbreak();
  keypad(stdscr, TRUE);
  noecho();

  height = 10;
  width = 100;
  starty = (LINES - height) / 2;
  startx = (COLS - width) / 2;
  printw("Press F1 to exit");
  refresh();
  my_win = create_newwin(25, 50, y, x);
  wmove(my_win, y, x);

  while((ch = getch()) != KEY_F(1))
    {
      if ((ch = getch()) == KEY_RIGHT)
        wmove(my_win, y++, x++);
      refresh();
  }

  endwin();
  return 0;
}
WINDOW *create_newwin(int height, int width, int starty, int startx)
{
  WINDOW *local_win;

  local_win = newwin(height, width, starty, startx);
  box(local_win, 0, 0);
  wrefresh(local_win);

  return (local_win);
}

【问题讨论】:

  • 对ncurses不太熟悉,但是create_newwin(25, 50, y, x)应该是create_newwin(starty, startx, height, width)吗?然后看起来您将光标放在带有wmove(my_win, y, x) 的右下角,并且当按下KEY_RIGHT 时,尝试将其向下和向右移动,而此时您已经走到了尽头朝着那个方向。
  • @Steve 我刚刚编辑了我的问题,让您看到我的 create_newwin。根据我的功能, create_newwin(25, 50, y, x) 似乎工作正常。

标签: c ncurses


【解决方案1】:

我只是玩了一下你的代码。

我认为主要问题是你在整个屏幕上做了refresh(),而刷新窗口wrefresh (my_win) 就足够了。

第二个问题:您确实等待了两次按键: 1. 在while 循环中 2.在if声明中。

getch()在 while 循环中就足够了。我们可以在循环中使用 ch 来检测按下了什么键。

我会做一个switch 而不是ifselection:

  while((ch = getch()) != 'q')
    {
        switch (ch)
        {
          case KEY_LEFT:
            x--;
            break;
          case KEY_RIGHT:
            x++;
            break;
          case KEY_UP:
            y--;
            break;
          case KEY_DOWN:
            y++;
            break;
        }

        wmove(my_win, y, x);
        wrefresh(my_win);
    }

我还删除了一些不合理的声明。

这是我所做的:

#include <stdio.h>
#include <ncurses.h>

WINDOW *create_newwin(int height, int width, int starty, int startx)
{
  WINDOW *local_win = newwin(height, width, starty, startx);
  box(local_win, 0, 0);
  wrefresh(local_win);

  return (local_win);
}

int main(int argc, char **argv)
{
  WINDOW *my_win;

  int ch;
  int x = 2;
  int y = 2;

  initscr();
  cbreak();
  keypad(stdscr, TRUE);
  noecho();

  printw("Press q to exit");
  refresh();
  my_win = create_newwin(10, 20, y, x);
  wmove(my_win, y, x);
  wrefresh(my_win);

  while((ch = getch()) != 'q')
    {
        switch (ch)
        {
          case KEY_LEFT:
            x--;
            break;
          case KEY_RIGHT:
            x++;
            break;
          case KEY_UP:
            y--;
            break;
          case KEY_DOWN:
            y++;
            break;
        }

        wmove(my_win, y, x);
        wrefresh(my_win);
    }

  endwin();
  return 0;
}

如果 x 或 y 大于或小于窗口大小,则光标不会移动,但值仍在变化。因此,请确保仅当值在窗口大小内时才允许减少或增加 x 和 y!

提示:

case KEY_LEFT:
   if (x>0) { x--; }
   break;

【讨论】:

    【解决方案2】:

    实际上,更好的解决方案是将wgetch 用于my_win 窗口,并消除对refreshwrefresh 的大部分调用。 wgetch (getch) 刷新正在读取的窗口。 Zehetner 示例的更改如下:

    --- foo3.c.orig 2015-04-02 19:53:18.000000000 -0400
    +++ foo3.c      2015-04-02 19:56:31.000000000 -0400
    @@ -1,11 +1,12 @@
     #include <stdio.h>
     #include <ncurses.h>
    
    +static
     WINDOW *create_newwin(int height, int width, int starty, int startx)
     {
       WINDOW *local_win = newwin(height, width, starty, startx);
       box(local_win, 0, 0);
    -  wrefresh(local_win);
    +  keypad(local_win, TRUE);
    
       return (local_win);
     }
    @@ -27,9 +28,8 @@
       refresh();
       my_win = create_newwin(10, 20, y, x);
       wmove(my_win, y, x);
    -  wrefresh(my_win);
    
    -  while((ch = getch()) != 'q')
    +  while((ch = wgetch(my_win)) != 'q')
         {
             switch (ch)
             {
    @@ -45,10 +45,12 @@
               case KEY_DOWN:
                 y++;
                 break;
    +          default:
    +            beep();
    +            break;
             }
    
             wmove(my_win, y, x);
    -        wrefresh(my_win);
         }
    
        endwin();
    

    或(结果程序):

    #include <stdio.h>
    #include <ncurses.h>
    
    static
    WINDOW *create_newwin(int height, int width, int starty, int startx)
    {
      WINDOW *local_win = newwin(height, width, starty, startx);
      box(local_win, 0, 0);
      keypad(local_win, TRUE);
    
      return (local_win);
    }
    
    int main(int argc, char **argv)
    {
      WINDOW *my_win;
    
      int ch;
      int x = 2;
      int y = 2;
    
      initscr();
      cbreak();
      keypad(stdscr, TRUE);
      noecho();
    
      printw("Press q to exit");
      refresh();
      my_win = create_newwin(10, 20, y, x);
      wmove(my_win, y, x);
    
      while((ch = wgetch(my_win)) != 'q')
        {
            switch (ch)
            {
              case KEY_LEFT:
                x--;
                break;
              case KEY_RIGHT:
                x++;
                break;
              case KEY_UP:
                y--;
                break;
              case KEY_DOWN:
                y++;
                break;
              default:
                beep();
                break;
            }
    
            wmove(my_win, y, x);
        }
    
      endwin();
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多