1

I am trying to import some data from a .csv file using a modified version of FileIO. I am supposed to use this data to show axis posture information. Therefore, values should be updated automatically every second. Then I created Q_PROPERTIES for every variable and created the code which gets data from the CSV file. I also added emit valueChanged() after every changing process.

void FileIO::getData()
{
    if (mSource.isEmpty()){
        emit error("source is empty");
    }
    QFile file(mSource);
    if (file.open(QIODevice::ReadOnly) ) {
        QString line;
        while (!file.atEnd()) {
            QByteArray line = file.readLine();
            xValue = line.split(',')[0].toFloat();
            emit xValueChanged();
            yValue = line.split(',')[3].toFloat();
            emit yValueChanged();
            zValue = line.split(',')[4].toFloat();
            emit zValueChanged();
            //Sleep(1000);
            qDebug()<< xValue <<yValue << zValue;
        }

        file.close();
    } else {
        emit error("Unable to open the file");
    }
}

So far, everything was fine but to spark the importing process I used Component.onCompleted.

    FileIO{
        id: dataCSV
        source: "C:/Users/Halil/yedekleme/Belgeler/build-serialGui-Desktop_Qt_5_14_2_MinGW_32_bit-Release/data.csv"
    }
    Component.onCompleted: {
        dataCSV.getData()
    }

...
            Entity
            {
                id: satEntity
                components: [
                    SceneLoader
                    {
                        id: sceneLoader
                        source:  "sat.stl"
                    },
                    Transform {
                        id:satTransform
                        rotationX: dataCSV.xValue
                        rotationY: dataCSV.yValue
                        rotationZ: dataCSV.zValue
                    }
                ]
            }

And the problem is I have to use these data to rotate a 3D object in real-time, but the engine doesn't load the ApplicationWindow before the Component.onCompleted is done. I see the values are updating -printing them to screen- but the transformer component cannot use them because the ApplicationWindow is not initialized before Component.onCompleted finishes, therefore I only see the last values.
last scene

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Lady Be Good
  • 253
  • 2
  • 12

1 Answers1

2

The problem is that the reading of the data is very fast so that our slow vision cannot see the change. In this case, what you should do is create a method that only reads a line and updates the value of xValue, yValue and zValue and then use a Timer to invoke that method every T seconds:

class FileIO: public QObject{
    Q_OBJECT
    Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
    Q_PROPERTY(qreal xValue READ xValue NOTIFY xValueChanged)
    Q_PROPERTY(qreal yValue READ xValue NOTIFY yValueChanged)
    Q_PROPERTY(qreal zValue READ xValue NOTIFY zValueChanged)
public:
    FileIO(QObject *parent=nullptr):
        QObject(parent), m_xValue(0.0), m_yValue(0.0), m_zValue(0.0), m_started(false)
    {
    }
    QString source() const
    {
        return m_file.fileName();
    }
    void setSource(QString source)
    {
        if (m_file.fileName() == source)
            return;
        m_file.setFileName(source);
        Q_EMIT sourceChanged();
    }
    qreal xValue() const
    {
        return m_xValue;
    }
    qreal yValue() const
    {
        return m_yValue;
    }
    qreal zValue() const
    {
        return m_zValue;
    }

    Q_INVOKABLE bool readNext(){
        tryStart();
        QString line;
        if(m_ts.readLineInto(&line)) {
            processLine(line);
            return true;
        }
        return false;
    }
Q_SIGNALS:
    void sourceChanged();

    void xValueChanged();
    void yValueChanged();
    void zValueChanged();
protected:
    void processLine(const QString & line){
        QStringList string_values = line.split(",");
        QVector<qreal> values(3);
        for(int i=0; i < values.size(); ++i){
            if(i < string_values.length()){
                values[i] = string_values[i].toDouble();
            }
        }
        m_xValue = values[0];
        m_yValue = values[1];
        m_zValue = values[2];
        Q_EMIT xValueChanged();
        Q_EMIT yValueChanged();
        Q_EMIT zValueChanged();
    }
private:
    bool tryStart(){
        if(m_started)
            return true;
        if(!m_file.open(QIODevice::ReadOnly)){
            qDebug() << m_file.errorString();
            m_ts.setDevice(nullptr);
            m_started = false;
            return false;
        }
        m_ts.setDevice(&m_file);
        m_started = true;
        return true;
    }
    QFile m_file;
    QTextStream m_ts;
    qreal m_xValue;
    qreal m_yValue;
    qreal m_zValue;
    bool m_started;
};
FileIO{
    id: dataCSV
    source: "C:/Users/Halil/yedekleme/Belgeler/build-serialGui-Desktop_Qt_5_14_2_MinGW_32_bit-Release/data.csv"
}
Timer{
    id: timer
    interval: 1000
    repeat: true
    onTriggered: {
        if(!dataCSV.readNext())
            dataCSV.stop()
    }
}
Component.onCompleted: timer.start()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you, code looks pretty well. I could understand generally but what causes the updating process is not clear. I mean in cpp side, it is clear enough but there should be a sparker that starts executing process of the header file on the QML side, shouldn't it?. I have not executed it yet, maybe it can work but I want to understand. – Lady Be Good Feb 20 '21 at 06:45