【问题标题】:Ncurses and Qt InteroperabilityNcurses 和 Qt 互操作性
【发布时间】:2014-01-03 13:43:50
【问题描述】:

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

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

更具体地说,如何获取用户输入并仍然使用QTimer 和信号槽机制?

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

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

【问题讨论】:

  • QT ncurses?同时有两个截然不同的用户界面?
  • @Kos Qt 不仅仅是你知道的 GUI 部分吗? :)
  • 有趣的组合 :-) 您是想在 Qt 中包装现有的基于 ncurses 的应用程序,还是基于这两个工具包编写新的应用程序?在第二种情况下,我建议检查一下,如果你不能只在 Qt 中做所有事情。
  • @JoachimPileborg 我将 QT 用于 Core 和 Sql,并使用 QTimer 来刷新时钟。

标签: c++ qt ncurses qtcore


【解决方案1】:
  1. 使用QSocketNotifier 通知stdin 上可用的内容。

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

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

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

在需要时将 ncurses 用于传统的文本模式用户界面,同时将 Qt 用于其他一切(定时、网络、具有基于文本的视图的数据模型、XML、QObjects 等)是一种完全有效的方法。

// 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"

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2010-09-06
      • 2017-08-12
      • 2010-09-21
      • 2020-07-27
      • 2018-10-08
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多