c++qtqml

Error "TypeError: Property 'smth' of object 'smth' is not a function"


I'm following a tutorial for a game on QML (link:https://www.youtube.com/watch?v=0Nbt2yO85d0&list=PLeYV3WjZWmHyYUe-BElUVNeFYTmpOQ9Xq&index=10&ab_channel=KALI)

I'm pretty sure that I have the exact same code, so why is the error appearing?

main.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <controller.h>

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

    QQmlApplicationEngine engine;

    Controller control;

    engine.rootContext()->setContextProperty("control", &control);

    const QUrl url(QStringLiteral("qrc:/game_tutorial/main.qml"));
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreated,
        &app,
        [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        },
        Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

controller.cpp:

#include "controller.h"

Controller::Controller(QObject *parent): m_x(50), m_y(50), m_xSpeed(10)
{

}

controller.h:

#ifndef CONTROLLER_H
#define CONTROLLER_H

#include <QObject>

class Controller : public QObject
{
    Q_OBJECT

    Q_PROPERTY(double x READ x WRITE setX NOTIFY xChanged)
    Q_PROPERTY(double y READ y WRITE setY NOTIFY yChanged)

    double x(){return m_x;}
    double y(){return m_y;}
    void setX(double val){if(m_x != val){m_x = val;emit xChanged();}}
    void setY(double val){if(m_y != val){m_y = val;emit yChanged();}}
    Q_INVOKABLE void moveLeft(){setX(m_x - m_xSpeed);}
    Q_INVOKABLE void moveRight(){setX(m_x + m_xSpeed);}

signals:
    void xChanged();
    void yChanged();

private:
    double m_x; // current position on x axis
    double m_y; // current position on y axis
    double m_xSpeed; //speed of movement on x

public:

    Controller(QObject *parent = nullptr);
};

#endif // CONTROLLER_H

main.qml:

import QtQuick


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

    Rectangle
    {
        id: move
        width: 50
        height: 50
        color: "red"
        x: control.x
        y: control.y
        focus: true

        Keys.onPressed: (event) =>
                        {
                            if(event.key === Qt.Key_D)
                            {
                                control.moveRight()
                            }
                            if(event.key === Qt.Key_A)
                            {
                                control.moveLeft()
                            }
                        }
    }
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)

project(game_tutorial VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)

qt_add_executable(appgame_tutorial
    main.cpp
)

qt_add_qml_module(appgame_tutorial
    URI game_tutorial
    VERSION 1.0
    QML_FILES main.qml
    SOURCES controller.h controller.cpp
)

# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appgame_tutorial PROPERTIES
#    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appgame_tutorial
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

target_link_libraries(appgame_tutorial
    PRIVATE Qt6::Quick)

include(GNUInstallDirs)
install(TARGETS appgame_tutorial
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

When I press A or D it says either

TypeError: Property 'moveRight' of object Controller(0x7f601ff8c0) is not a function

or

TypeError: Property 'moveLeft' of object Controller(0x7f601ff8c0) is not a function

I'd be very thankful if you would fix my code.


Solution

  • You can put public: over double x(), like this:

    //...
    Q_PROPERTY(double x READ x WRITE setX NOTIFY xChanged)
    Q_PROPERTY(double y READ y WRITE setY NOTIFY yChanged)
    
    public:
        double x(){return m_x;}
        double y(){return m_y;}
    //...