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
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
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();
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.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.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.
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