How to run a C++ function when QML button is clicked? Using QQmlApplicationEngine



  • myclass.h
    @#ifndef MYCLASS_H
    #define MYCLASS_H

    #include <QDebug>
    #include <QObject>

    class MyClass : public QObject
    {
    public:
    MyClass();

    public slots:
    void buttonClicked();
    void buttonClicked(QString &in);
    };

    #endif // MYCLASS_H@


    myclass.cpp
    @#include "myclass.h"

    MyClass::MyClass()
    {
    }

    void MyClass::buttonClicked()
    {
    // Do Something
    }

    void MyClass::buttonClicked(QString &in)
    {
    qDebug() << in;
    }@


    main.cpp
    @#include <QApplication>
    #include <QQmlApplicationEngine>
    #include <myclass.h>
    #include <QQmlContext>

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
    MyClass myClass;  // A class containing my functions
    
    // Trying to "SetContextProperty" as I saw people do it to achieve C++/QML connection
    QQmlContext *context = new QQmlContext(engine.rootContext());
    context->setContextProperty("_myClass", &myClass);
    
    return app.exec();
    

    }@

    ............
    I want to use a function in myClass class which takes a QString parameter when a QML button is clicked ..
    When I compile & run .. it all goes smoothly. But when I click on the button .. it shows this error in the debugger:
    qrc:///main.qml:80: ReferenceError: _myClass is not defined
    ~> "Line 80 in my QML file":
    @74: MouseArea {
    75: id: mouseArea1
    76: anchors.fill: parent
    77: hoverEnabled: true;
    78: onEntered: { rectangle1.border.width = 2 }
    79: onExited: { rectangle1.border.width = 1 }
    80: onClicked: _myClass.buttonClicked("Worked?")
    81: }@



  • Welcome to Qt DevNet!

    I think you missed Q_OBJECT macro in MyClass declaration
    @
    class MyClass : public QObject
    {
    Q_OBJECT // <-- This one
    public:
    @



  • [quote author="andreyc" date="1406088144"]Welcome to Qt DevNet!

    I think you missed Q_OBJECT macro in MyClass declaration[/quote]

    Hi andreyc,
    Now myclass.h looks like this:
    @#ifndef MYCLASS_H
    #define MYCLASS_H

    #include <QDebug>
    #include <QObject>

    class MyClass: public QObject
    {
    Q_OBJECT

    public:
    MyClass();

    public slots:
    void buttonClicked();
    void buttonClicked(QString &in);
    };

    #endif // MYCLASS_H
    @

    But now my code wouldn't compile at all! it gives me this compile error:
    @C:\Users\Dell\Documents\Workspace\ProjectOne\myclass.h:7: error: undefined reference to `vtable for MyClass'@



  • Have you rebuild the whole project after you added Q_OBJECT ?



  • [quote author="andreyc" date="1406130397"]Have you rebuild the whole project after you added Q_OBJECT ?[/quote]

    Oh sorry, I feel like an idiot now.
    I've rebuilt the whole project, and it runs perfectly.

    But when I click on the button I get this in the debugger:
    @qrc:///main.qml:80: ReferenceError: _myClass is not defined@
    <~ Same main problem.



  • It works for me.

    • main.cpp
      @
      int main(int argc, char *argv[])
      {
      QApplication app(argc, argv);

      QQmlApplicationEngine engine;
      engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
      QQmlContext *item = engine.rootContext();
      MyClass myClass;
      item->setContextProperty("_myClass", &myClass);

      return app.exec();
      }
      @

    • MyClass.h
      @
      class MyClass : public QObject
      {
      Q_OBJECT
      public:
      //explicit MyClass(QObject *parent = 0) : QObject(parent) {}
      MyClass() {}

      signals:

      public slots:
      void buttonClicked(QString in)
      {
      qDebug() << "buttonClicked" << in;
      }

    };
    @

    • main.qml
      @
      import QtQuick 2.2
      import QtQuick.Controls 1.1

    ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }
    
    
    Rectangle {
        id: rectangle1
        width: 100
        height: 100
        color: "red"
        border.color: "black"
        border.width: 5
        radius: 10
    }
    
    MouseArea {
        id: mouseArea1
        anchors.fill: parent
        hoverEnabled: true;
        onEntered: { rectangle1.border.width = 2 }
        onExited: { rectangle1.border.width = 1 }
        onClicked: _myClass.buttonClicked("Worked?")
    }
    

    }
    @



  • If your problem is still not resolved, Can you try item->setContextProperty("_myClass", &myClass); before loading the QML ?



  • Thanks guys, it's solved.

    I just had to remove the first declaration of my slot:
    myclass.h

    @#ifndef MYCLASS_H
    #define MYCLASS_H

    #include <QDebug>
    #include <QObject>

    class MyClass : public QObject
    {
    public:
    MyClass();

    public slots:
    //void buttonClicked(); <~ This had to be removed in order to make it work
    void buttonClicked(QString &in);
    };

    #endif // MYCLASS_H
    @


Log in to reply
 

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