Keyboard key emulation from C++ to QML



  • I want to emulate keyboard key press event from C++ and that would affect in qml.

    In my application i need to operate GUI from keyboard and also from UART.
    I am using qml from GUI. and its working great with keyboard. But i want same gui functionalities from UART bytes reception (ex. UP/DOWN uart frame). My UART code works fine. But i am unable to find way to emulate QKeyEvent from C++ file.

    main.cpp

    int main(int argc, char **argv)
    {
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
        UART *uart = new UART(&engine);
        uart->UARTInit();
    
        engine.load(QUrl(QStringLiteral("qrc:///HomePage.qml")));
        engine.rootContext()->setContextProperty(QLatin1String("uart"), uart);
    
        return app.exec();
    }
    

    UART.cpp

    void UART::readRequest()
    {
            QKeyEvent key_press(QKeyEvent::KeyPress, Qt::Key_P, Qt::NoModifier);
            QCoreApplication::sendEvent(engine.rootObjects().first(), &key_press);
    }
    

    HomePage.qml

    ApplicationWindow {
        id: rootWindow
        width: Screen.width
        height: Screen.height
        visible: true
        visibility: Window.FullScreen
    
        Item {
            id: it
            focus: true
    
           .
           .
    
            Keys.onPressed: {
                switch(event.key) {
                case Qt.Key_P:
                    gstpipe.play()
                    videoview.visible = true
                    event.accepted = true;
                    break;
               }
          }
       }
    }
    

    so i am getting error in "QCoreApplication::sendEvent(engine.rootObjects().first(), &key_press);"
    error: 'engine' was not declared in this scope

    So how to correctly send QkeyEvent to QML?



  • I have found one solution for the error: 'engine' was not declared in this scope

    UART.h

    class UART : public QObject
    {
        Q_OBJECT
        QQmlApplicationEngine m_engine;
    public:
        explicit UART(QQmlApplicationEngine *engine, QObject *parent = 0);
    }
    

    UART.cpp

    UART::UART(QQmlApplicationEngine *engine, QObject *parent) :
        QObject(parent), m_engine(engine)
    {
    
    }
    void UART::readRequest()
    {
            QKeyEvent key_press(QKeyEvent::KeyPress, Qt::Key_P, Qt::NoModifier);
            QCoreApplication::sendEvent(m_engine.rootObjects().first(), &key_press);
    }
    

    Now i am not getting any error while building.
    But when UART request is received and QCoreApplication::sendEvent(m_engine.rootObjects().first(), &key_press); is executed i am getting following error.

    ASSERT: "!isEmpty()" in file /usr/include/qt5/QtCore/qlist.h, line 287
    The program has unexpectedly finished.
    

    So whats' the missing here?


  • Moderators

    QQmlApplicationEngine is a QObject, so you are not allowed to copy it!

    So, it should help if you declared m_engine as pointer in your UART class:

    QQmlApplicationEngine *m_engine;
    

    And then called that pointer from your request:

    void UART::readRequest()
    {
            QKeyEvent key_press(QKeyEvent::KeyPress, Qt::Key_P, Qt::NoModifier);
            QCoreApplication::sendEvent(m_engine->rootObjects().first(), &key_press);
    }
    

    For more information about why QObjects can't be copied, see Qt docs.



  • @sierdzio Thanks for the reply.
    But as i am new to Qt and all. I am asking this question.
    If i create new

    QQmlApplicationEngine *m_engine;
    

    pointer ? how can i refer it to my original

    QQmlApplicationEngine engine;
    

    And i need to pass keyevent to engine .


  • Moderators

    No, no, you do not need to change anything in your main.cpp, the engine can still be created on stack there.

    QQmlApplicationEngine engine;
    /// ...
    UART *uart = new UART(&engine); // here you pass a reference (pointer) to your UART class - everything is fine
    

    Just changing the UART class as I indicated in my previous post should be enough.



  • Thanks for the Reply.
    I get everything working from below changes.

    UART.cpp

    UART::UART(QObject *parent) :
        QObject(parent)
    {
        m_engine = (QQmlApplicationEngine *)parent;
    }
    
    void UART::readRequest()
    {
            QKeyEvent key_press(QKeyEvent::KeyPress, Qt::Key_P, Qt::NoModifier);
            QCoreApplication::sendEvent(m_engine->rootObjects().first(), &key_press);
    }
    

    UART.h

    class UART : public QObject
    {
        Q_OBJECT
    
    public:
        explicit UART(QObject *parent = 0);
    
    signals:
    
    protected:
    
    public slots:
        void UARTInit();
    
    private:
        QQmlApplicationEngine *m_engine;
    
    private slots:
        void readRequest();
    
    };
    

    And main.cpp without any change as per your previous reply.

    Thanks ... :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.