Ncurses和Qt互操作性

时间:2013-12-16 08:26:35

标签: c++ qt ncurses qtcore

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

我需要在CPU使用率和应用程序响应能力之间做出最佳折衷。

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

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

nodelay(stdscr,true); while(1) { sleep(1); getch(); processInput(); }

2 个答案:

答案 0 :(得分:8)

  1. 使用QSocketNotifier通知stdin上可用的内容。

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

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

  4. 以下代码在接收输入时回显输入,并且每秒输出*。这适用于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"
    

答案 1 :(得分:0)

我发现信号槽机制在循环中不起作用的答案是QCoreApplication :: processEvents(); 所以,接收信号:

while(1)
{
    sleep(1);
    getch();
    processInput();
    QCoreApplication::processEvents();
}