Merlin Newcomb
Merlin Newcomb

Reputation: 13

Method in class inheriting QObject is identified as property when called, doesn't run method

Basically, I have a project that I'm working on that's supposed to be a graphical game of Tic-Tac-Toe, and method calls to a class called "Game" (and any method calls at all) from the main qml file don't work. This error is returned:

TypeError: Property 'takeTurn' of object [object Object] is not a function

I've inherited QObject in this class, as well as included the Q_OBJECT macro and labelled the method as a Q_INVOKABLE.

The code compiles and links perfectly fine, this is a run-time error.

Here's the relevant code to help:

Game.hpp:

#define GAME_HPP

#include "Board.hpp"
#include <ostream>

#include <QObject>

class Game : public QObject
{
    Q_OBJECT;
    public:
        //...
        Q_INVOKABLE void takeTurn(int x, int y);
        Q_INVOKABLE bool checkWin();

        friend std::ostream& operator<<(std::ostream&, const Game&);
    private:
        char player_;
        int turns_;
        Board board_;
};

std::ostream& operator<<(std::ostream&, const Game&);

#endif // GAME_HPP

Game.cpp:

#include <iostream>

#include <QObject>
#include <QApplication>

using std::cout;
using std::endl;

//...
void Game::takeTurn(int x, int y)
{
    QWindow* app = QApplication::topLevelWindows()[0];
    cout << app << endl;
    board_.setTile(x, y, player_);
    player_ == 'X' ? player_ = 'O' : player_ = 'X';
    turns_++;
}
//...

main.cpp:

#include "Game.hpp"

#include <iostream>
#include <QGuiApplication>
#include <QQmlApplicationEngine>

using std::cout;
using std::endl;

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);
    qmlRegisterType<Game>("com.myself", 1, 0, "Game");
    qmlRegisterType<Board>("com.myself", 1, 0, "Board");

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/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();
}

main.qml:

import QtQuick.Window 2.12
import com.myself 1.0

Window {
    visible: true
    width: 600
    height: 600
    title: qsTr("TicTacToe")

    Item {
        //...

        MouseArea {
            id: mouseArea1
            anchors.fill: parent
            onClicked: {
                Game.takeTurn(0,0)
            }
        }
    }
//...

}
//...

Upvotes: 1

Views: 43

Answers (1)

eyllanesc
eyllanesc

Reputation: 243973

You have registered Game as a type, so what you need to do is create an object of that type, the error points to that problem:

// ...
Window {
    visible: true
    width: 600
    height: 600
    title: qsTr("TicTacToe")
    Game {
        id: game
    }

    // ...
    Item {
        // ...
        MouseArea {
            id: mouseArea1
            anchors.fill: parent
            onClicked: {
                game.takeTurn(0,0)
            }
       }
    }
    // ...

Upvotes: 0

Related Questions