配置键重复延迟以检测是否按下了键

时间:2015-12-17 23:34:20

标签: c terminal key delay curses

我在C中编写一个程序,它使用ncurses来检查是否按下了某个键。问题是有一个关键的重复延迟。

如果我在终端中按住键'a',则在重复输入'a'之前会有短暂的延迟。我希望能够知道它是否从实际按下它的位置被按下。

如何在终端中暂时将此延迟更改为等于0?我目前正在使用Mac OSX 10.10.5。

2 个答案:

答案 0 :(得分:1)

使用ncurses(任何curses实现),您将使用getch而不是getchar。后者是C标准I / O输入功能。

有人建议 Create a function to check for key press in unix using ncurses ,其中包含一个值得一提的答案。它使用nodelay来消除通常在getch中为转义序列的连续字节花费的时间。在curses中,您总是在等待与否之间进行权衡,因为转义序列可能无法在一次read操作中到达。这里显示的示例报告没有字符可用的情况,并在这种情况下暂停(休眠)一小段时间。

如果您只想查看读取的字符,可以消除该暂停(但会使您的程序占用大量CPU时间):

#include <ncurses.h>

int kbhit(void)
{
    int ch = getch();

    if (ch != ERR) {
        ungetch(ch);
        return 1;
    } else {
        return 0;
    }
}

int main(void)
{
    initscr();

    cbreak();
    noecho();
    nodelay(stdscr, TRUE);

    scrollok(stdscr, TRUE);
    while (1) {
        if (kbhit()) {
            printw("Key pressed! It was: %d\n", getch());
        }
    }
}

或(认识到存在权衡),使用napms暂停时间,但减少使用的CPU时间:

#include <ncurses.h>

int kbhit(void)
{
    int ch = getch();

    if (ch != ERR) {
        ungetch(ch);
        return 1;
    } else {
        return 0;
    }
}

int main(void)
{
    initscr();

    cbreak();
    noecho();
    nodelay(stdscr, TRUE);

    scrollok(stdscr, TRUE);
    while (1) {
        if (kbhit()) {
            printw("Key pressed! It was: %d\n", getch());
        } else {
            napms(20);
        }
    }
}

答案 1 :(得分:1)

尝试此操作以忽略缓冲的密钥重复:

int key;
if ((key = getch()) != ERR) {
  while (getch() == key);
}

在上下文中:

//example.c

#include <ncurses.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int pos_x = 0;
  int max_x = 0, max_y = 0;
  int key = 0;
  int on = 1;

  initscr();
  noecho();
  cbreak();
  curs_set(FALSE);
  keypad(stdscr, TRUE);
  nodelay(stdscr, TRUE);
  getmaxyx(stdscr,max_y,max_x);

  while(1) {
    clear();
    mvprintw(0, 0, "Press, hold and release L-R arrow keys. Press UP/DOWN to toggle function.");
    mvprintw(1, 0, "Skip buffered repeats: %s", (on ? "ON" : "OFF"));
    mvprintw(2, pos_x, "@");
    refresh();
    usleep(50000);
    getmaxyx(stdscr,max_y,max_x);
    key = getch();

    // skip buffered repeats                                                                                     
    if (on) {
      if (key != ERR) {
        while (getch() == key);
      }
    }
    //                                                                                                           

    switch (key) {
    case KEY_LEFT:
      pos_x += (pos_x > 0 ? -1 : 0); break;
    case KEY_RIGHT:
      pos_x += (pos_x < max_x - 1 ? 1 : 0); break;
    case KEY_UP:
      on = 1; break;
    case KEY_DOWN:
      on = 0; break;
    }
  }
  endwin();
}

使用gcc example.c -lncurses -oexample && ./example

编译并运行