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 не будет опубликован. Обязательные поля помечены *