Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

I am having some sort of problem with Q_PROPERTY



  • Please forgive me I have made a class when at this point I don't need one.
    Anyway I get these errors:

    moc_tiledata.obj:-1: error: LNK2005: "public: void __cdecl TileData::tilesChanged(void)" (?tilesChanged@TileData@@QEAAXXZ) already defined in tiledata.obj
    moc_tiledata.obj:-1: error: LNK2005: "public: void __cdecl TileData::locxChanged(void)" (?locxChanged@TileData@@QEAAXXZ) already defined in tiledata.obj
    moc_tiledata.obj:-1: error: LNK2005: "public: void __cdecl TileData::locyChanged(void)" (?locyChanged@TileData@@QEAAXXZ) already defined in tiledata.obj
    moc_tiledata.obj:-1: error: LNK2005: "public: void __cdecl TileData::locmChanged(void)" (?locmChanged@TileData@@QEAAXXZ) already defined in tiledata.obj
    C:\Users\damon\Documents\QT\build-skydevils-Desktop_Qt_5_15_2_MSVC2015_64bit-Debug\debug\skydevils.exe:-1: error: LNK1169: one or more multiply defined symbols found
    

    main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include "tiledata.h"
    #include <QQmlContext>
    int main(int argc, char *argv[])
    {
    #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif
    
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<TileData>("com.andyindustries.tiledata",1,0,"TileData");
    
        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();
    }
    
    

    mymap.h:

    #ifndef MYMAP_H
    #define MYMAP_H
    
    #include <QtCore>
    class MyMap
    {
    public:
        ~MyMap();
        void setMap(QString ins);
        int maxx;
        int maxy;
        int **tiles;
    };
    
    #endif // MYMAP_H
    
    

    mymap.cpp:

    #include "mymap.h"
    
    MyMap::~MyMap()
    {
    
    }
    
    void MyMap::setMap(QString ins)
    {
        bool readx = true;
        int numx = 1;
        int numy = 1;
        for(int i=0;i<ins.length();i++){
            if(ins.mid(i,1) == "\n"){
                readx = false;
                numy++;
            }
            if (readx && ins.mid(i,1) == ",") numx++;
        }
        maxx = numx;
        maxy = numy;
        tiles = new int *[numx];
        for (int i=0;i<numx;i++) tiles[i] = new int[numy];
        int curnum = 0;
        int placx = 0;
        int placy = 0;
        for(int i=0;i<ins.length();i++){
            if (ins.at(i).toLatin1() > 47 && ins.at(i).toLatin1() < 59){
                curnum *= 10;
                curnum += ins.at(i).toLatin1() - 48;
                if (i == ins.length() - 1) tiles[placx][placy] = curnum;
            }
            if (ins.mid(i,1) == "," || ins.mid(i,1) == "\n"){
                tiles[placx][placy] = curnum;
                curnum = 0;
                placx++;
                if (placx == numx){
                    placx = 0;
                    placy++;
                }
            }
        }
    }
    
    

    tiledata.h:

    #ifndef TILEDATA_H
    #define TILEDATA_H
    
    #include <QObject>
    #include <QFile>
    #include <QTextStream>
    #include <QDebug>
    
    #include "mymap.h"
    
    class TileData : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(int tiles READ tiles WRITE settiles NOTIFY tilesChanged)
        Q_PROPERTY(int plocx READ plocx WRITE setplocx NOTIFY locxChanged)
        Q_PROPERTY(int plocy READ plocy WRITE setplocy NOTIFY locyChanged)
        Q_PROPERTY(int plocm READ plocm WRITE setplocm NOTIFY locmChanged)
    public:
        explicit TileData(QObject *parent = nullptr);
        int tiles();
        int plocx();
        int plocy();
        int plocm();
        void settiles(int inv);
        void setplocx(int inv);
        void setplocy(int inv);
        void setplocm(int inv);
    signals:
        void tilesChanged();
        void locxChanged();
        void locyChanged();
        void locmChanged();
    
    private:
        int locx;
        int locy;
        int locm;
        QVector<MyMap> myMaps;
    };
    
    #endif // TILEDATA_H
    
    

    tiledata.cpp

    #include "tiledata.h"
    
    TileData::TileData(QObject *parent) : QObject(parent)
    {
        QString inDat;
        QFile fil("/tileref/tiledata.csv");
        if(!fil.open(QFile::ReadOnly | QFile::Text)){
    
        }
        QTextStream in(&fil);
        inDat = in.readAll();
        fil.close();
        MyMap tempM;
        tempM.setMap(inDat);
        myMaps.push_back(tempM);
    }
    
    int TileData::tiles()
    {
        if (locx > -1 && locx < myMaps.at(locm).maxx && locy > -1 && locy < myMaps.at(locm).maxy && locm < myMaps.size()){
            return myMaps.at(locm).tiles[locx][locy];
        }else{
            return -1;
        }
        emit tilesChanged();
    }
    
    int TileData::plocx()
    {
        return locx;
    }
    
    int TileData::plocy()
    {
        return locy;
    }
    
    int TileData::plocm()
    {
        return locm;
    }
    
    void TileData::settiles(int inv)
    {
    
    }
    
    void TileData::setplocx(int inv)
    {
        locx = inv;
        emit locxChanged();
    }
    
    void TileData::setplocy(int inv)
    {
        locy = inv;
        emit locyChanged();
    }
    
    void TileData::setplocm(int inv)
    {
        locm = inv;
        emit locmChanged();
    }
    
    void TileData::tilesChanged(){
    
    }
    
    void TileData::locxChanged(){
    
    }
    
    void TileData::locyChanged(){
    
    }
    void TileData::locmChanged(){
    
    }
    
    
    

    and now my Qml which is main.qml:

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Dialogs 1.2
    import QtQuick.Controls 2.5
    import com.andyindustries.tiledata 1.0
    
    ApplicationWindow {
        width: 640
        height: 600
        visible: true
        title: qsTr("******") // censord
        property bool needLoad: true
        property int curframe: 0
        property var frameVals: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    
        TileData{
            id:td
        }
    
        Timer{
            interval: 50; running: true; repeat: true
            onTriggered:{
                if (needLoad){
                    td.locm = 0;
                    for (var y=0;y<5;y++){
                        td.plocy = y;
                        for (var x=0;x<5;x++){
                            td.plocx = x;
                            frameVals[x + y * 5] = td.tiles;
                        }
                    }
                    needLoad = false;
                }
    
                curframe = (curframe + 1) % 4
                mycanvas.requestPaint()
            }
        }
    
        function getName(inv){
            var retv = "/images/bloc";
            var part = 0;
            for (var i=0;i<4;i++){
                part = Math.floor(inv / Math.pow(16, (3 - i))) % 16
                if (part > 9){
                    retv += String.fromCharCode(55 + part)
                }else{
                    retv += String.fromCharCode(48 + part)
                }
            }
            retv += ".png"
            return retv
        }
    
        function fldName(inv){
            var retv = "/images/field";
            retv += String.fromCharCode(48 + inv)
            retv += ".png"
            return retv
        }
    
        Canvas{
            id: mycanvas
            anchors.centerIn: parent
            width: 512
            height: 512
            property string oneEl: ""
            Component.onCompleted:  {
    
    
                for (var i=0;i<10;i++){
                    oneEl = getName(i)
                    loadImage(mycanvas.oneEl);
    
                }
                oneEl = getName(65535);
                loadImage(oneEl)
                for (var j=0;j<8;j++){
                    oneEl = fldName(j)
                    loadImage(mycanvas.oneEl);
    
                }
            }
    
    
    
            onPaint: {
                var ctx = getContext("2d");
                for (var y=0;y<5;y++){
                    for (var x=0;x<5;x++){
                        if (frameVals[x + y * 5] < 10000 || frameVals[x + y * 5] == 65535){
                            oneEl = getName(frameVals[x + y * 5]);
                        }else{
                            switch (frameVals[x + y * 5]){
                            case 65531:
                                oneEl = fldName(curframe)
                                break;
                            case 65532:
                                oneEl = fldName(curframe + 4);
                                break;
                            case 65533:
                                oneEl = fldName(3 - curframe)
                                break;
                            case 65534:
                                oneEl = fldName(3 - curframe + 4)
                                break;
                            }
                        }
                        ctx.drawImage(mycanvas.oneEl,x * 96,y * 96)
                    }
                }
            }
        }
    }
    
    

  • Qt Champions 2017

    @AI_Messiah said in I am having some sort of problem with Q_PROPERTY:
    In tiledata.cpp:

    void TileData::tilesChanged()
    

    One doesn't implement signals, the moc does that for you. Remove these. Btw the linker is more than descriptive here (emphasis mine):
    moc_tiledata.obj:-1: error: LNK2005: "public: void __cdecl TileData::tilesChanged(void)" (?tilesChanged@TileData@@QEAAXXZ) already defined in tiledata.obj

    Also seems appropriate you also read this:
    https://en.wikipedia.org/wiki/One_Definition_Rule



  • I did what you said, there was one thing that I had to change that you would have overlooked, but this loads the tile = 0 for all tiles.


Log in to reply