Как использовать библиотеки JavaScript в QML

#javascript #qt #qml

#javascript #qt #qml

Вопрос:

Я использую некоторые библиотеки javascript с QML в версии 5.12.2. Некоторые из них работают как Proj4JS. Но я получаю ошибки при использовании geographiclib.js библиотека с QML. Как можно импортировать библиотеку JavaScript в QML?

main.qml:

 import QtQuick 2.12
import QtQuick.Window 2.12
import "geographiclib.js" as MyGeo
Window {
    visible: true
    width: 640
    height: 480
    Component.onCompleted: {
        var Geodesic = MyGeo.GeographicLib.Geodesic,
            DMS = MyGeo.GeographicLib.DMS,
            geod = Geodesic.WGS84;
        var r = geod.Inverse(23, 22, 44, 29);
        console.log("distance is: ", r.s12.toFixed(3)   " m")
    }
}
  

Ошибка:

 qrc:/geographiclib.js:3081: ReferenceError: window is not defined
qrc:/main.qml:9: TypeError: Cannot read property 'Geodesic' of undefined
  

Комментарии:

1. Куда вы поместили файл .js (во время выполнения)? Я думаю, что это должно быть прикреплено в качестве ресурса в .qrc

2. Файл js находится в qrc: <file>main.qml</file><file>geographiclib.js</file>

Ответ №1:

Самый простой способ сделать это — сделать GeographicLib доступным по всему миру:

В конце geographiclib.js файл, изменение

 window.GeographicLib = geo;
  

Для

 this.GeographicLib = geo;
  

и тогда вы можете просто использовать:

main.qml:

 import QtQuick 2.12
import QtQuick.Window 2.12
import "geographiclib.js" as ThenItWillBeAvailableGlobally
Window {
    visible: true
    width: 640
    height: 480
    Component.onCompleted: {
        var Geodesic = GeographicLib.Geodesic,
            DMS = GeographicLib.DMS,
            geod = Geodesic.WGS84;
        var r = geod.Inverse(23, 22, 44, 29);
        console.log("distance is: ", JSON.stringify(r))
    }
}
  

В результате:

 qml: distance is:  {"lat1":23,"lat2":44,"lon1":22,"lon2":29,"a12":21.754466225665134,"s12":2416081.7576307985,"azi1":13.736139413215236,"azi2":17.669059640534535}
  

Это вы не хотите менятьgeographiclib.js файл вообще, вы могли бы добавить глобальный объект window, используя, например:

window.js:

 this.window = this;
  

а затем использовать:

 import QtQuick 2.12
import QtQuick.Window 2.12
import "window.js" as ThenWindowWillBeAvailableGlobally
import "geographiclib.js" as ThenGeographicLibWillBeAvailableGlobally
Window {
    visible: true
    width: 640
    height: 480
    Component.onCompleted: {
        var Geodesic = GeographicLib.Geodesic,
            DMS = GeographicLib.DMS,
            geod = Geodesic.WGS84;
        var r = geod.Inverse(23, 22, 44, 29);
        console.log("distance is: ", JSON.stringify(r))
    }
}
  

Если вы не хотите добавлять какие-либо глобальные переменные, но вы рады отредактироватьgeographiclib.js файл, тогда вы могли бы просто переместить строку 68 в начало файла:

 var GeographicLib = {};
/*
 * Geodesic routines from GeographicLib translated to JavaScript.  See
 * https://geographiclib.sourceforge.io/html/js/
  

и в конце файла измените

   } else {
    /******** otherwise just pollute our global namespace ********/
    window.GeographicLib = geo;
  }
});
  

Для

   } else if (typeof window === 'object') {
    /******** otherwise just pollute our global namespace ********/
    window.GeographicLib = geo;
  }
});
  

и тогда ваш main.qml будет работать просто отлично.

Комментарии:

1. Спасибо за потрясающий ответ! Мне не нужно будет запускать React Native, если я продолжу использовать пакеты npm с QML 🙂 Я надеюсь, что компания Qt добавит подробную документацию об этом. Кстати, я ошибся, указав расстояние, оно должно быть "distance is: ", r.s12

Ответ №2:

Вы импортируете файл javascript правильно.

Из документа:

QML предоставляет среду хоста JavaScript, адаптированную для написания приложений QML. Эта среда отличается от среды хоста, предоставляемой браузером или серверной средой JavaScript, такой как Node.js . Например, QML не предоставляет объект window или DOM API, которые обычно встречаются в среде браузера.

Комментарии:

1. Я думал, что с поддержкой Ecmascript 7 в версии 5.12.2 QML может принимать объект window. Библиотека JavaScript содержит объект window. К сожалению, я не знаю, как подогнать библиотеку javascript под QML. Я пробовал такие библиотеки, как Qmljsfy (модуль qml для преобразования пакетов npm в файлы javascript QML), это не сработало.

2. Спасибо. Я не получаю ошибку окна, но я получаю TypeError: Cannot read property 'Geodesic' of undefined