bonjour, en copiant votre code je reçois les erreur: js: Fetch API cannot load file:///C:/test.pdf. URL scheme "file" is not supported. js: Uncaught (in promise) DataCloneError: Failed to execute 'postMessage' on 'Worker': TypeError: Failed to fetch could not be cloned. voici mon code: WebEngineView { id: webview property string viewer:"file:///H:/flightradar24/web/viewer.html" // chemin absolu pointant vers notre fichier viewer.html dernièrement téléchargé. property string pathPdf:"C:/test.pdf" // chemin absolu pointant vers le document pdf à afficher. // le code ci-dessous permettra d'afficher une page blanche si au moins l'un des deux chemin n'est pas renseigné url: if (viewer && pathPdf) { viewer + "?file=" + pathPdf } } ou est mon erreur? merci pour votre aide
très bon blog.
Non celui qui a vraiment pris les devants c'est Amnell car il a déjà fait un tuto sur le sujet il y a 4 ans : Communication entre QML et C++/Qt. Rendons à César ce qui est à César. C'est d'ailleurs à partir de ce tutoriel là que j'ai élaboré ma propre solution car je ne trouve pas que celle d'Amnell soit idéale (mais pour en discuter c'est sur ce thread et pas ailleurs).
air-dex et merci pour ton commentaire. Pour tout te dire, j'ai fait ce billet pour illustrer rapidement une des manières de dialoguer entre du code QML et du code C++ afin d'aider un membre (voir cette discussion) Mais comme tu as pu le lire au début du billet, j'accorde largement le fait que cette méthode n'est pas la plus "corporate", mais c'est de loin la plus simple. J'avais prévu d'illustrer les autres méthodes, du coup tu as pris un peu les devants ...
Perso je n'aime pas cette façon de faire. Je n'aime pas manipuler le QML côté C++. Je préfère largement que les deux restent indépendants. Si je dois mélanger les deux, alors je préfère largement exposer mes classes C++ à QML : Côté QML : Code QML : Sélectionner tout - Visualiser dans une fenêtre à part 12345678910111213141516171819202122232425262728293031323334353637383940// main.qml import QtQuick 2.5 import QtQuick.Controls 1.4 import MyControls 3.14 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") menuBar: MenuBar { Menu { title: qsTr("File") MenuItem { text: qsTr("&Open") onTriggered: console.log("Open action triggered"); } MenuItem { text: qsTr("Exit") onTriggered: Qt.quit(); } } } Label { id: label text: qsTr("Hello World") x: 5 ; y: 5 width: parent.width height: 50 } Button { x: 5 ; y: 100 text: qsTr("Click here") onClicked: label.text = comCpp.txt(); // les lignes qui suivent expliquent ce qu'est comCpp.txt() } ComCpp { id: comCpp } } Côté C++ : Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part 1234567891011121314151617// comcpp.hpp #ifndef COMCPP_HPP #define COMCPP_HPP #include <QObject> #include <QString> class ComCpp : public QObject { Q_OBJECT public: ComCpp(); Q_INVOKABLE QString txt(); static void declareQML(); }; #endif // COMCPP_HPP Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part 1234567891011121314// comcpp.cpp #include "comcpp.hpp" #include <QtQml> ComCpp::ComCpp() : QObject() {} void ComCpp::declareQML() { qmlRegisterType<ComCpp>("MyControls", 3, 14, "ComCpp"); } QString ComCpp::txt(){ QString r = "You have clicked on QML Button"; return r; } Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part 123456789101112// main.cpp #include <QApplication> #include <QQmlApplicationEngine> #include "comcpp.hpp" int main(int argc, char *argv[]) { QApplication app(argc, argv); ComCpp::declareQML(); // On expose notre classe à QML ici QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } Je trouve ça nettement plus propre. Mon code C++ est totalement indépendant du QML. Côté QML, tout mon backend est dans une librairie QML a priori comme les autres, ici nommée "MyControls" et qui est dans sa version 3.14. Pour aller plus loin :Si j'ai besoin d'accéder à des attributs, alors je les mets dans des Q_PROPERTY.On peut aussi appeler les slots de la classe C++ côté QML, mais perso j'évite. Généralement on n'appelle pas les slots comme on appellerait une fonction ou méthode classique, d'où les Q_INVOKABLE .Si j'ai besoin d'enums, alors cf. cette réponse StackOverflow que j'ai écrite il y a quelques temps : "how to access C++ enum from QML?" (<frime>ma réponse la mieux notée sur SO au moment où j'écris ce commentaire </frime>).S'il y a besoin de connecter des signaux C++ et des slots QML ou vice-versa, alors je fais ça côté QML, comme je le ferais avec des signaux et des slots QML classiques. OSEF si en fait c'est du C++ derrière.
// main.qml import QtQuick 2.5 import QtQuick.Controls 1.4 import MyControls 3.14 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") menuBar: MenuBar { Menu { title: qsTr("File") MenuItem { text: qsTr("&Open") onTriggered: console.log("Open action triggered"); } MenuItem { text: qsTr("Exit") onTriggered: Qt.quit(); } } } Label { id: label text: qsTr("Hello World") x: 5 ; y: 5 width: parent.width height: 50 } Button { x: 5 ; y: 100 text: qsTr("Click here") onClicked: label.text = comCpp.txt(); // les lignes qui suivent expliquent ce qu'est comCpp.txt() } ComCpp { id: comCpp } }
// comcpp.hpp #ifndef COMCPP_HPP #define COMCPP_HPP #include <QObject> #include <QString> class ComCpp : public QObject { Q_OBJECT public: ComCpp(); Q_INVOKABLE QString txt(); static void declareQML(); }; #endif // COMCPP_HPP
// comcpp.cpp #include "comcpp.hpp" #include <QtQml> ComCpp::ComCpp() : QObject() {} void ComCpp::declareQML() { qmlRegisterType<ComCpp>("MyControls", 3, 14, "ComCpp"); } QString ComCpp::txt(){ QString r = "You have clicked on QML Button"; return r; }
// main.cpp #include <QApplication> #include <QQmlApplicationEngine> #include "comcpp.hpp" int main(int argc, char *argv[]) { QApplication app(argc, argv); ComCpp::declareQML(); // On expose notre classe à QML ici QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }
Re, ^^ On est pas obligé d'attendre l'acte II pour ça... C'est vrai que j'aurai pu en parler. Mon avis sur LocalStorage Très bien excepté le fait que ça ne gère qu'un seul type de BDD, comprendre par là que si on souhaite utiliser PostgreSQL et MySQL, il faut oublier LocalStorage. Gros avantage de QML c'est que l'on peut créer ses propres Items depuis du code Python ou C++ et qui pourront donc ensuite être utilisés comme on le souhaite dans un document QML. (Pour ceux qui connaissent QML, la première remarque sera : pourquoi créer cet Item, alors que l'on pourrait tout simplement tout en faire en C++ ou Python. Pour débattre de cette question, je vous invite à participer à ce sondage) L'un de mes projets est donc de créer un nouvel Item de gestion de base de données permettant d'utiliser n'importe quel SGBD... mais ça, ça va prendre un peu de temps. Utilité du code produit Je travaille sur deux projets nécessitants de stocker des données. Le code est donc fait pour me faciliter la vie lorsque je vais devoir sérieusement attaquer la partie logique des projets (là je ne suis encore que sur la partie conception graphique). Évidemment, si ces quelques lignes peuvent servir à d'autres, tant mieux. En espérant avoir quelque peu répondu à tes interrogations.
Dommage de devoir attendre ton Act II pour avoir un avis sur le LocalStorage ou une explication sur le bût du code produit. Cordialement, Patrick Kolodziejczyk.
QML permet de faire des appli Desktop et mobile. Ce langage est issu en majorité de Qt, mais possède en effet beaucoup de points communs avec JavaScript à tel point, que les fonctions JavaScripts sont reconnues par QML. Dans un autre registre, tu verras à quel point ces deux langages sont très proches dans mon prochain billet : Connexion et Gestion d'une base de données (act I) Si tu as des commentaires, conseils, ... n'hésite surtout pas ++ J
Je ne connais absolument pas QML. D'après wikipédia, c'est influencé par JavaScript. Mais,c'est bien pour du Qt application "Desktop" ? D'ailleurs, cela ressemble beaucoup au libraire JavaScript utilisant canvas. C'est similaire dans l'usage ? Car, la transformation est très siminiare : Code qml : Sélectionner tout - Visualiser dans une fenêtre à part transform: Rotation { origin.x: 0; origin.y: height/2; angle: 180; axis { x: 1; y: 0; z: 0 }} Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part 12var rotate = d3.svg.transform().rotate(-45); var translate = d3.svg.transform().translate(200, 100); Cordialement, Patrick Kolodziejczyk.
transform: Rotation { origin.x: 0; origin.y: height/2; angle: 180; axis { x: 1; y: 0; z: 0 }}
var rotate = d3.svg.transform().rotate(-45); var translate = d3.svg.transform().translate(200, 100);