Qt QJSEngine Hello world

—

от автора

Данный пример построен на примере из книги М.Шлее «Qt профессиональное программирование на Qt» «Черепашья графика». Для лучшего понимания работы советую почитать раздел «Язык сценариев Qt Scripts».

В примере будет реализован простой терминал, в который можно вводить команды. Результат выполнения команд будет отображаться в этом же терминале. Пользовательский интерфейс будет реализован на QML.

Создадим проект Qt Quick

image

Опишем форму. Файл 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         }     } }

Форма

image

Добавим в проект классы AppCore и Console, немного допишем 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(); } 

В конструкторе класса AppCore мы добавили экземпляр класса Console в QJSEngine, так же мы определили что будем обращаться к методам этого класса через «console»

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

Сигнал appEndTextArea(const QString& text) — добавление текста в textAreaLog в
main.qml.

Сигнал clearTextArea() — очистить область вывода текста textAreaLog в main.qml.

Слот slotEvaluate(const QString& code) — выполнение js кода, введенного в textEditInput в main.qml.

Допишем в main.qml обработчики сигналов:

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

Так же допишем в textEditInput сигнал, вызова слота 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()         } 

Теперь при вводе команды в textEditInput и нажатии Enter команда будет передана в slotEvaluate в AppCore. При нажатии ESC поле textEditInput очистится.

При запуске приложения, если мы введем в textEditInput команду console.log(«Hello world»), то в поле textAreaLog увидим Hello world. Если ввести команду неизвестную QJSEngine, то в терминале высветится ошибка.

image

Таким образом, мы написали приложение, в котором мы можем вызывать методы подключенных к QJSEngine классов и выводить результаты выполнения этих методов. Кто то скажет «А при чем тут JS? Ведь классы написаны на С++?», но это уже другая история…

Ссылка проекта на github


ссылка на оригинал статьи https://habr.com/ru/post/481142/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *