2011-09-25 18 views

Respuesta

5

Qt no maneja los eventos de la consola, solo puede leer \n líneas terminadas desde la consola.

Necesita utilizar API nativas u otras bibliotecas (curses).

+0

gracias por la ayuda –

5

Aquí hay una solución para Linux. El uso de estos mensajes

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

que he hecho de esta manera:

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); 
    } 
} 

Y entonces simplemente comenzar nuevo hilo para leer claves:

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

* actualizado (añadido Restauración de la configuración de terminales en dejar de fumar)

3

Si sólo necesita 'Salir' tal vez el siguiente fragmento ayudará (c + +11 y qt5 requerido):

#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(); 
    f.wait(); 
    return ret; 
} 
+0

funciona bien! ¿Podría explicar por qué necesita 'f.wait()' después de 'exec()'? – spartawhy117

+0

Es el punto de sincronización explícito donde el subproceso async() se une de forma segura. El objeto 'f' std :: future destructor no puede bloquear explícitamente hasta que la banda de rodamiento se una (eso necesita exploración) – vrogach

Cuestiones relacionadas