Qt QJSEngine Bonjour tout le monde

Cet exemple est basé sur un exemple du livre de M. Schlee "Qt Professional Qt Programming" "Turtle Graphics" . Pour une meilleure compréhension du travail, je vous conseille de lire la section "Qt Scripts Scripting Language".

Dans l'exemple, un simple terminal sera implémenté dans lequel des commandes pourront être saisies. Le résultat de l'exécution des commandes sera affiché dans le même terminal. L'interface utilisateur sera implémentée en QML.

Créer un projet rapide Qt

image

Nous décrivons le formulaire. Fichier Main.qml:

import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.0 Window { id: window visible: true width: Screen.width/2 height: Screen.height/2 title: qsTr(" jsEnjine") property string consoleFontFamily: "Consolas" property int fontPixelSize: 14 TextArea { id: textAreaLog anchors.bottom: rectangle.top anchors.bottomMargin: 3 anchors.right: parent.right anchors.rightMargin: 3 anchors.left: parent.left anchors.leftMargin: 3 anchors.top: parent.top anchors.topMargin: 3 readOnly: true } Rectangle { id: rectangle height: 25 anchors.right: parent.right anchors.rightMargin: 3 anchors.left: parent.left anchors.leftMargin: 3 anchors.bottom: parent.bottom anchors.bottomMargin: 3 border.color: "#0c0a0a" TextEdit { id: textEditInput anchors.right: parent.right anchors.rightMargin: 5 anchors.left: parent.left anchors.leftMargin: 5 anchors.bottom: parent.bottom anchors.bottomMargin: 5 anchors.top: parent.top anchors.topMargin: 5 font.pixelSize: fontPixelSize } } } 

Formulaire

image

Ajoutez les classes AppCore et Console au projet, ajoutez un peu de main.c

 #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "appcore.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); AppCore appCore; QQmlApplicationEngine engine; QQmlContext *context = engine.rootContext();//   //      ,  //    //     context->setContextProperty("appCore",&appCore); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if(engine.rootObjects().isEmpty()) return -1; return app.exec(); } 

appcore.h

 #ifndef APPCORE_H #define APPCORE_H #include <QObject> #include <QJSEngine> #include "console.h" class AppCore : public QObject { Q_OBJECT public: explicit AppCore(QObject *parent = nullptr); private: QJSEngine appScriptEngine; Console *userConsole; signals: Q_INVOKABLE void appEndTextArea(const QString& text); Q_INVOKABLE void clearTextArea(); public slots: Q_INVOKABLE void slotEvaluate(const QString& code); }; #endif // APPCORE_H 

appcore.c

 #include "appcore.h" AppCore::AppCore(QObject *parent) : QObject(parent) { userConsole = new Console(this); QJSValue val = appScriptEngine.newQObject(userConsole); appScriptEngine.globalObject().setProperty("console",val); connect(userConsole, SIGNAL(appEndTextArea(QString)),this,SIGNAL(appEndTextArea(QString))); connect(userConsole, SIGNAL(clearTextArea()),this,SIGNAL(clearTextArea())); } void AppCore::slotEvaluate(const QString& code) { QJSValue result = appScriptEngine.evaluate(code); if(result.isError()){ QString er = QString("   %1: %2").arg(result.property("lineNumber").toInt()).arg(result.toString()); emit appEndTextArea(er); } } 

console.h

 #ifndef CONSOLE_H #define CONSOLE_H #include <QObject> class Console : public QObject { Q_OBJECT public: explicit Console(QObject *parent = nullptr); Q_INVOKABLE void log(const QString& message); Q_INVOKABLE void clear(); signals: Q_INVOKABLE void appEndTextArea(const QString& text); Q_INVOKABLE void clearTextArea(); }; #endif // CONSOLE_H 

console.cpp

 #include "console.h" Console::Console(QObject *parent) : QObject(parent) { } void Console::log(const QString& message) { emit appEndTextArea(message); } void Console::clear() { emit clearTextArea(); } 

Dans le constructeur de la classe AppCore, nous avons ajouté une instance de la classe Console à QJSEngine , et nous avons également déterminé que nous accéderons aux méthodes de cette classe via "console"

 QJSValue val = appScriptEngine.newQObject(userConsole); appScriptEngine.globalObject().setProperty("console",val); 

Signal appEndTextArea (const QString & text) - ajout de texte à textAreaLog dans
main.qml .

Signal clearTextArea () - efface la zone de sortie de texte textAreaLog dans main.qml .

Slot slotEvaluate (const QString & code) - exécution du code js entré dans textEditInput dans main.qml .

Ajoutons des gestionnaires de signaux dans main.qml :

 Connections{ target: appCore onAppEndTextArea:{ textAreaLog.cursorPosition = textAreaLog.length; textAreaLog.append(text); } onClearTextArea:{ textAreaLog.cursorPosition=0; textAreaLog.text = ""; } } 

Nous ajoutons également un signal au signal textEditInput , appelant le slot void slotEvaluate (const QString & code) :

 TextEdit { id: textEditInput anchors.right: parent.right anchors.rightMargin: 5 anchors.left: parent.left anchors.leftMargin: 5 anchors.bottom: parent.bottom anchors.bottomMargin: 5 anchors.top: parent.top anchors.topMargin: 5 font.pixelSize: fontPixelSize Keys.onReturnPressed:{ if(textEditInput.text == "")return; appCore.slotEvaluate(text) clear() } Keys.onEscapePressed: clear() } 

Maintenant, lorsque vous tapez une commande dans textEditInput et appuyez sur Entrée, la commande sera transmise à slotEvaluate dans AppCore . Lorsque vous appuyez sur ÉCHAP, le champ textEditInput est effacé.

Lorsque l'application démarre, si nous entrons la commande console.log ("Hello world") dans textEditInput, nous verrons Hello world dans le champ textAreaLog . Si vous entrez une commande QJSEngine inconnue, une erreur s'affiche dans le terminal.

image

Ainsi, nous avons écrit une application dans laquelle nous pouvons appeler les méthodes des classes connectées à QJSEngine et afficher les résultats de ces méthodes. Quelqu'un dira: "Qu'est-ce que JS a à voir avec ça?" Après tout, les classes sont écrites en C ++? » , Mais c'est une autre histoire ...

Projet de lien sur github

Source: https://habr.com/ru/post/fr481142/


All Articles