Ncurses和Qt互操作性 [英] Ncurses and Qt Interoperability

查看:144
本文介绍了Ncurses和Qt互操作性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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



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

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


解决方案


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


  2. 在循环中调用非阻塞 getch(),直到没有更多输入可用。这是非常重要的:通知器只会在新的数据可用时通知,但这并不意味着它会通知每个字符!如果你一次收到多个字符,你通常只会得到一个通知 - 因此你必须保持发布非阻塞 getch(),直到它返回


  3. 您还应该阅读所有可用的数据,


下面的代码在接收输入时回显输入, * 每秒。这在Linux和OS X上工作,不能移植到Windows。要退出,请按需要的旧版文字模式用户界面,使用 ncurses Q 。



<利用Qt的其他(定时,网络,基于文本的视图,XML,QObjects的数据模型等)是一个完全有效的方法。

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

类Worker:public QObject
{
Q_OBJECT
QSocketNotifier m_notifier {0,QSocketNotifier :: Read,this};
QBasicTimer m_timer;
Q_SLOT void readyRead(){
//可以调用这个方法,没有可以读取的数据。
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(); //数据可能已经可用,无需通知
m_timer.start(1000,this);
}
};

int main(int argc,char * argv [])
{
QCoreApplication a {argc,argv};
Worker w;
auto win = initscr();
clear()
cbreak(); //所有输入立即可用
noecho(); // no echo
printw(Press< q> to quit\);
keypad(win,true); //特殊键被解释并返回为单个int从getch()
nodelay(win,true); // getch()是非阻塞调用
auto rc = a.exec();
endwin();
return rc;
}

#includemain.moc


Having a Qt and ncurses based application, what is the best way to refresh the screen every second, while waiting for user input? (e.g. show the clock and get user input).

I need the best compromise between CPU usage and application responsiveness.

To be more specific with the question, how to get user input and still use QTimer and the signal-slot mechanism?

When using the code below, the timers doen't work.

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

解决方案

  1. Use QSocketNotifier to be notified of things being available on stdin.

  2. Call nonblocking getch() in a loop until no more input is available. This is vitally important: the notifier will notify only when new data is available, but this doesn't mean that it notifies on every character! If you receive multiple characters at a time, you will usually get just one notification - thus you must keep issuing non-blocking getch() until it returns ERR meaning that no more data is available at the moment.

  3. You should also read all of the data that became available in the time before the socket notifier became attached.

The code below echoes the input as it receives it, and additionally outputs a * every second. This works on Linux and OS X, and is not portable to Windows. To quit, press Q.

Using ncurses for a legacy text-mode user interface, where desired, while leveraging Qt for everything else (timing, networking, data models with text-based views, XML, QObjects, etc.) is a perfectly valid approach.

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

这篇关于Ncurses和Qt互操作性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆