如何在 Qt 控制台应用程序中处理按键事件?

发布于 2024-12-06 11:52:55 字数 27 浏览 0 评论 0原文

例如,当您按“Esc”时,应用程序结束。

For example, that when you press "Esc", the application ends.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

り繁华旳梦境 2024-12-13 11:52:55

这是针对 Linux 的解决方法。使用这些帖子

从标准输入捕获字符,无需等待按下回车键
https://stackoverflow.com/a/912796/2699984

我做了这样的:

ConsoleReader。 h

#ifndef CONSOLEREADER_H
#define CONSOLEREADER_H

#include <QThread>

class ConsoleReader : public QThread
{
    Q_OBJECT
signals:
    void KeyPressed(char ch);
public:
   ConsoleReader();
   ~ConsoleReader();
   void run();
};

#endif  /* CONSOLEREADER_H */

ConsoleReader.cpp

#include "ConsoleReader.h"
#include <stdio.h>
#include <unistd.h>
#include <termios.h>

static struct termios oldSettings;
static struct termios newSettings;

/* Initialize new terminal i/o settings */
void initTermios(int echo) 
{
  tcgetattr(0, &oldSettings); /* grab old terminal i/o settings */
  newSettings = oldSettings; /* make new settings same as old settings */
  newSettings.c_lflag &= ~ICANON; /* disable buffered i/o */
  newSettings.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
  tcsetattr(0, TCSANOW, &newSettings); /* use these new terminal i/o settings now */
}

/* Restore old terminal i/o settings */
void resetTermios(void) 
{
  tcsetattr(0, TCSANOW, &oldSettings);
}

/* Read 1 character without echo */
char getch(void) 
{
  return getchar();
}

ConsoleReader::ConsoleReader()
{
  initTermios(0);
}

ConsoleReader::~ConsoleReader()
{
  resetTermios();
}

void ConsoleReader::run()
{
    forever
    {
        char key = getch();        
        emit KeyPressed(key);
    }
}

然后启动新线程来读取密钥:

ConsoleReader *consoleReader = new ConsoleReader();
connect (consoleReader, SIGNAL (KeyPressed(char)), this, SLOT(OnConsoleKeyPressed(char)));
consoleReader->start();

*更新(添加退出时恢复终端设置)

Here is a workaround for linux. Using these posts

Capture characters from standard input without waiting for enter to be pressed
https://stackoverflow.com/a/912796/2699984

I've made it like this:

ConsoleReader.h

#ifndef CONSOLEREADER_H
#define CONSOLEREADER_H

#include <QThread>

class ConsoleReader : public QThread
{
    Q_OBJECT
signals:
    void KeyPressed(char ch);
public:
   ConsoleReader();
   ~ConsoleReader();
   void run();
};

#endif  /* CONSOLEREADER_H */

ConsoleReader.cpp

#include "ConsoleReader.h"
#include <stdio.h>
#include <unistd.h>
#include <termios.h>

static struct termios oldSettings;
static struct termios newSettings;

/* Initialize new terminal i/o settings */
void initTermios(int echo) 
{
  tcgetattr(0, &oldSettings); /* grab old terminal i/o settings */
  newSettings = oldSettings; /* make new settings same as old settings */
  newSettings.c_lflag &= ~ICANON; /* disable buffered i/o */
  newSettings.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
  tcsetattr(0, TCSANOW, &newSettings); /* use these new terminal i/o settings now */
}

/* Restore old terminal i/o settings */
void resetTermios(void) 
{
  tcsetattr(0, TCSANOW, &oldSettings);
}

/* Read 1 character without echo */
char getch(void) 
{
  return getchar();
}

ConsoleReader::ConsoleReader()
{
  initTermios(0);
}

ConsoleReader::~ConsoleReader()
{
  resetTermios();
}

void ConsoleReader::run()
{
    forever
    {
        char key = getch();        
        emit KeyPressed(key);
    }
}

And then just start new thread to read keys:

ConsoleReader *consoleReader = new ConsoleReader();
connect (consoleReader, SIGNAL (KeyPressed(char)), this, SLOT(OnConsoleKeyPressed(char)));
consoleReader->start();

*UPDATED (added restoring terminal settings on quit)

月下客 2024-12-13 11:52:55

如果您只需要“退出”,也许以下代码片段会有所帮助(需要 c++11 和 qt5):

#include <iostream>
#include <future>

#include <QCoreApplication>
#include <QTimer>

int main(int argc, char *argv[])
{
    QCoreApplication application(argc, argv);
    bool exitFlag = false;

    auto f = std::async(std::launch::async, [&exitFlag]{
        std::getchar();
        exitFlag = true;
    });

    QTimer exitTimer;
    exitTimer.setInterval(500);
    exitTimer.setSingleShot(false);

    QObject::connect(&exitTimer,
                     &QTimer::timeout,
                     [&application,&exitFlag] {
        if (exitFlag)
            application.quit();
    });

    exitTimer.start();

    std::cout << "Started! Press Enter to quit...";
    int ret =  application.exec();
    std::cout.flush();
    f.wait();
    return ret;
}

If you need only 'quit' maybe the following snippet will help (c++11 and qt5 required):

#include <iostream>
#include <future>

#include <QCoreApplication>
#include <QTimer>

int main(int argc, char *argv[])
{
    QCoreApplication application(argc, argv);
    bool exitFlag = false;

    auto f = std::async(std::launch::async, [&exitFlag]{
        std::getchar();
        exitFlag = true;
    });

    QTimer exitTimer;
    exitTimer.setInterval(500);
    exitTimer.setSingleShot(false);

    QObject::connect(&exitTimer,
                     &QTimer::timeout,
                     [&application,&exitFlag] {
        if (exitFlag)
            application.quit();
    });

    exitTimer.start();

    std::cout << "Started! Press Enter to quit...";
    int ret =  application.exec();
    std::cout.flush();
    f.wait();
    return ret;
}
标点 2024-12-13 11:52:55

Qt 不处理控制台事件,它只能从控制台读取以 \n 结尾的行。

您需要使用本机 API 或其他库(curses)。

Qt doesn't handle console events, it can just read \n-terminated lines from the console.

You need to use native APIs or other libraries (curses).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文