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

QFileSystemWatcher fileChanged() signal to QML slot



  • Hello,

    I have a GUI display that shows data values from an external file. I want to be able to update the display whenever the values in the file change. I'm trying to use QFileSystemWatcher fileChanged() to emit a signal to the SLOT in qml that will update the display. I can't seem to figure out the sending of the signal when the file is read.

    //readJSON.h
    
    class readJSON :public QObject
    {
        Q_OBJECT
    
    public:
        readJSON();
    
    public slots:
        QString readingJson(const QString &name);
    
    };
    
    
    //main.cpp
    
    int main(int argc, char *argv[])
    {
    
    
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        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);
    
    
    
        QFileSystemWatcher watcher;
        watcher.addPath("data.json");
    
        readJSON* myGlobal = new readJSON();
    
        engine.rootContext()->setContextProperty("myGlobalObject", myGlobal);
    
    
        QObject::connect(&watcher, SIGNAL(fileChanged()),
                         myGlobal, SLOT(updateDisplay()));
        
        engine.load(url);
    
        return app.exec();
    }
    
    //main.qml
    
    Window {
        visible: true
        width: 800
        height: 800
        title: qsTr("Screen Display")
    
    
        DisplaysForm {
    
            function callCPP(text) {
                var dataOne = myGlobalObject.readingJson(text)
                dataOne = parseFloat(dataOne)
    
                return dataOne
            }
    
           function updateDisplay() {
    
                var value = callCPP("Engine_Spd")
                engSpd_txt.text = value
    
                var value1 = callCPP("Engine_Power")
                engPwr_txt.text = value1
           }
    
    


  • hi

    @texasRanger said in QFileSystemWatcher fileChanged() signal to QML slot:

    QObject::connect(&watcher, SIGNAL(fileChanged()),
    myGlobal, SLOT(updateDisplay()));

    you are trying to connect the signal fileChanged of watcher to the slot updateDisplay of myGlobal, but myGlobal has no slot
    updateDisplay, that function (slot) is defined in QML

    here is an example how to connect c++ signal to qml function
    https://forum.qt.io/topic/116084/c-signal-to-a-qml-file/4

    also you sould use "new" signal/slot syntax
    https://wiki.qt.io/New_Signal_Slot_Syntax



  • Export watcher:

    int main(int argc, char *argv[])
    {
    
    
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        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);
    
    
    
        QFileSystemWatcher watcher;
        watcher.addPath("data.json");
    
        readJSON myGlobal;
    
        engine.rootContext()->setContextProperty("myGlobalObject", &myGlobal);
        engine.rootContext()->setContextProperty("watcher", &watcher);
        
        engine.load(url);
    
        return app.exec();
    }
    

    and use Connections:

    Window {
        visible: true
        width: 800
        height: 800
        title: qsTr("Screen Display")
    
    
        DisplaysForm {
    
            function callCPP(text) {
                var dataOne = myGlobalObject.readingJson(text)
                dataOne = parseFloat(dataOne)
    
                return dataOne
            }
    
           function updateDisplay() {
    
                var value = callCPP("Engine_Spd")
                engSpd_txt.text = value
    
                var value1 = callCPP("Engine_Power")
                engPwr_txt.text = value1
           }
        Connections{
            target: watcher
            function onFileChanged(path){
                    console.log(path)
                    updateDisplay()
            }
        }
    }