Ncurses和Qt互操作性

Mar*_*ian 6 c++ qt ncurses qtcore

拥有基于Qt和ncurses的应用程序,在等待用户输入的同时每秒刷新屏幕的最佳方法是什么?(例如,显示时钟并获取用户输入).

我需要CPU使用率和应用程序响应能力之间的最佳折衷.

更具体的问题是,如何获得用户输入仍然使用QTimer和信号槽机制?

使用下面的代码时,计时器不起作用.

nodelay(stdscr,true); while(1) { sleep(1); getch(); processInput(); }
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 8

  1. 用于QSocketNotifier通知可用的内容stdin.

  2. getch()在循环中调用非阻塞,直到没有更多输入可用.这非常重要:通知程序仅在数据可用时才会通知,但这并不意味着它会通知每个角色!如果您一次收到多个字符,通常只会收到一个通知 - 因此您必须继续发出非阻塞通知,getch()直到它返回ERR意味着此时没有更多数据可用.

  3. 您还应该读取套接字通知程序附加之前的所有可用数据.

下面的代码在接收输入时回显输入,并且*每秒输出一次.这适用于Linux和OS X,不能移植到Windows.要退出,请按Q.

在需要时使用ncurses用于遗留文本模式用户界面,同时将Qt用于其他所有内容(时间,网络,具有基于文本的视图的数据模型,XML,QObject等)是一种非常有效的方法.

// https://github.com/KubaO/stackoverflown/tree/master/questions/ncurses-20606318
#include <QtCore>
#include <ncurses.h>

class Worker : public QObject
{
   Q_OBJECT
   QSocketNotifier m_notifier{0, QSocketNotifier::Read, this};
   QBasicTimer m_timer;
   Q_SLOT void readyRead() {
      // It's OK to call this with no data available to be read.
      int c;
      while ((c = getch()) != ERR) {
         printw("%c", (char)(c <= 255 ? c : '?'));
         if (c == 'q' || c == 'Q') qApp->quit();
      }
   }
   void timerEvent(QTimerEvent * ev) {
      if (ev->timerId() != m_timer.timerId()) return;
      printw("*");
      refresh();
   }
public:
   Worker(QObject * parent = 0) : QObject(parent) {
      connect(&m_notifier, SIGNAL(activated(int)), SLOT(readyRead()));
      readyRead(); // data might be already available without notification
      m_timer.start(1000, this);
   }
};

int main(int argc, char *argv[])
{
   QCoreApplication a{argc, argv};
   Worker w;
   auto win = initscr();
   clear();
   cbreak(); // all input is available immediately
   noecho(); // no echo
   printw("Press <q> to quit\n");
   keypad(win, true); // special keys are interpreted and returned as single int from getch()
   nodelay(win, true); // getch() is a non-blocking call
   auto rc = a.exec();
   endwin();
   return rc;
}

#include "main.moc"
Run Code Online (Sandbox Code Playgroud)