問題描述
有一個基于 Qt 和 ncurses 的應用程序,在等待用戶輸入時每秒刷新屏幕的最佳方法是什么?(例如,顯示時鐘并獲取用戶輸入).
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).
我需要在 CPU 使用率和應用程序響應能力之間取得最佳折衷.
I need the best compromise between CPU usage and application responsiveness.
更具體地說,如何獲取用戶輸入并仍然使用 QTimer
和信號槽機制?
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(); }
推薦答案
使用
QSocketNotifier
來通知stdin
上可用的東西.
Use
QSocketNotifier
to be notified of things being available onstdin
.
在循環中調用非阻塞 getch()
直到沒有更多輸入可用.這一點非常重要:只有當新數據可用時,通知程序才會通知,但這并不意味著它會通知每個字符!如果您一次收到多個字符,您通常只會收到一個通知 - 因此您必須繼續發出非阻塞 getch()
直到它返回 ERR
意味著沒有更多數據目前可用.
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.
您還應該讀取在連接套接字通知程序之前可用的所有數據.
You should also read all of the data that became available in the time before the socket notifier became attached.
下面的代碼在接收到輸入時回顯,并且每秒額外輸出一個 *
.這適用于 Linux 和 OS X,不能移植到 Windows.要退出,請按 Q.
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.
在需要時將 ncurses 用于傳統文本模式用戶界面,同時將 Qt 用于其他所有方面(計時、網絡、具有基于文本的視圖的數據模型、XML、QObjects 等)是一種完全有效的方法.
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
");
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 互操作性的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!