【问题标题】:How to handle keypress events in a Qt console application?如何在 Qt 控制台应用程序中处理按键事件?
【发布时间】:2011-09-25 02:42:19
【问题描述】:

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

【问题讨论】:

    标签: c++ qt event-handling keypress


    【解决方案1】:

    这是 linux 的解决方法。使用这些帖子

    Capture characters from standard input without waiting for enter to be pressed 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();
    

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

    【讨论】:

    • consoleReader-&gt;start(); -- 你的意思是run()吗?
    • 我在我的项目中使用了这个,如果工作得很好。请注意,密钥代码取决于您使用的终端类型。如果您通过 SSH 连接而不是使用终端会话,这也可能会改变。
    【解决方案2】:

    如果您只需要“退出”,也许以下 sn-p 会有所帮助(需要 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;
    }
    

    【讨论】:

    • 效果很好!你能解释一下为什么在exec()之后需要f.wait()吗?
    • 这是 async() 线程安全连接的显式同步点。 'f' 对象 std::future 析构函数可能不会显式阻塞,直到踏面连接(需要探索)
    • 必须在int ret = application.exec();行前加上std::cout.flush();
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 2012-07-07
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      相关资源
      最近更新 更多