Evgenii Legotckoi
Evgenii Legotckoi11 октября 2018 г. 14:04

Qt/C++ - Урок 084. Как запускать JavaScript код в C++ приложении на примере работы с двумя переменными

Допустим, перед вами встала задача по выполнению JavaScript кода в C++ приложении. Например есть набор выходных данный или переменных, названия которых заранее известны, а также имеются куски JavaScript кода, который что-то делает с этими переменными. Причём ещё имеется алгоритм, который при наличии каких-либо условий будет выбирать. какой именно JavaScript код следует запускать.

Также, вы не можете просто взять и переписать тот JavaScript код на C++ код и хардкорно добавить его в приложение. Поскольку таких кусков кода очень много, при этом их обслуживанием занимаются другие люди и постоянно добавляют новые кусочки кода.

То есть в данном случае набор входных данных и JavaScript код для нас является данными, в некотором роде контентом, который мы запускаем в работу с помощью определённого алгоритма, по которому выбираем, при каких условиях для одного и того же набора входных переменных выбирать тот или иной кусок JavaScript кода.

Надеюсь, что я понятно объяснил, почему нам нужно запускать выполнение JavaScript кода в C++ приложении.

Предлагаю написать приложение, которое имеет два поля ввода имён переменных, два поля ввода с вводом значений этих переменных в формате double, в случае ввода значения отличного от типа данных double будем устанавливать значение переменной Undefined .

Также добавим поле ввода TextEdit для написания JavaScript кода, который мы будем выполнять в нашем приложении.

И последнее поле ввода будет называться Result (это будет TextEdit), которое будет отвечать за вывод новых посчитанных значений введённых нами переменных.

Также добавим QPushButton, который будет запускать выполнение JavaScript кода.

Приложение будет выглядеть так, как на рисунке ниже.


Структура проекта

Напишем проект с минимальной структурой. По сути проект имеет структуру, которая создаётся по умолчанию.

Единственное важное отличие от дефолтного pro файла будет в том, что нам потребуется подключить script модуль.

Это делается в JSCalculation.pro файле.

QT       += core gui widgets script

Widget.ui

В данной статье я не буду описывать, как создавал форму приложения в Qt Designer, это нам не так важно, да и к теме статьи не относится. Лишь перечислю те объекты, которые будут использоваться в исходных кодах виджета с наименованием их классом

  • nameLineEdit_1 - QLineEdit
  • nameLineEdit_2 - QLineEdit
  • valueLineEdit_1 - QLineEdit
  • valueLineEdit_2 - QLinEdit
  • execPushButton - QPushButton
  • javaScriptTextEdit - QPlainTextEdit
  • resultTextEdit - QPlainTextEdit

А теперь приступим непосредственно к реализации нашего проекта

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    // Всё по умолчанию, кроме этого слота, который выполнит JavaScript и посчитает переменные
    void onExecPushButtonClicked();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

Widget.cpp

А теперь сам программный код приложения

#include "Widget.h"
#include "ui_Widget.h"

// Нам понадобяться следующие классы
#include <QScriptEngine>
#include <QScriptContext>
#include <QScriptValue>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    connect(ui->execPushButton, &QPushButton::clicked, this, &Widget::onExecPushButtonClicked);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::onExecPushButtonClicked()
{
    // Создадим объект движка JavaScript
    QScriptEngine engine;
    // Возьмём из него контекст, в котором будем работать
    // В данном случае создаётся новый контекст
    QScriptContext* context = engine.pushContext();

    // Возьмём имена переменных, с которыми должны работать
    const QString var_1 = ui->nameLineEdit_1->text();
    const QString var_2 = ui->nameLineEdit_2->text();

    // Установим переменные, попытавшись сконвертировать текст QLineEdit полей в double
    bool ok = false;

    double value = ui->valueLineEdit_1->text().toDouble(&ok);
    if (ok)
    {
        // Устанавливаем переменные со значением в качестве свойств объекта активации скрипта
        context->activationObject().setProperty(var_1, value);
    }
    else
    {
        // Если конвертация не удалась, то значение будет Undefined
        context->activationObject().setProperty(var_1, QScriptValue::UndefinedValue);
    }

    value = ui->valueLineEdit_2->text().toDouble(&ok);
    if (ok)
    {
         // Устанавливаем переменные со значением в качестве свойств объекта активации скрипта
        context->activationObject().setProperty(var_2, value);
    }
    else
    {
        // Если конвертация не удалась, то значение будет Undefined
        context->activationObject().setProperty(var_2, QScriptValue::UndefinedValue);
    }

    // Запускаем выполнение скрипта
    engine.evaluate(ui->javaScripTextEdit->toPlainText());

    // Очищаем поле вывада результата от предыдущих значений
    ui->resultTextEdit->clear();
    // Выводим текущее состояние переменных
    ui->resultTextEdit->appendPlainText(var_1 + " = " + context->activationObject().property(var_1).toString());
    ui->resultTextEdit->appendPlainText(var_2 + " = " + context->activationObject().property(var_2).toString());

    // Удаляем контекст
    engine.popContext();

    // Поскольку QScriptEngine создан на стеке метода, то он удалится автоматически по завершении метода
}

Заключение

Можете сначала ввести названия переменных и их значения, чтобы убедиться, что всё отлично работает и без JavaScript кода.

Также приложение не должно падать и завершаться с ошибками. Если JavaScript код, который вы будете вводить и как показано в самом начале статьи, даёт не тот результат, который вы ожидаете, то возможно стоит внимательно посмотреть на ваш JavaScript код, скорее всего вы допустили ошибку. Также QScriptEngine поддерживает некоторый стандартный функционал JavaScript, например библиотеку Math ( Она тоже будет работать).

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
e
  • ehot
  • 31 марта 2024 г. 14:29

C++ - Тест 003. Условия и циклы

  • Результат:78баллов,
  • Очки рейтинга2
B

C++ - Тест 002. Константы

  • Результат:16баллов,
  • Очки рейтинга-10
B

C++ - Тест 001. Первая программа и типы данных

  • Результат:46баллов,
  • Очки рейтинга-6
Последние комментарии
k
kmssr8 февраля 2024 г. 18:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко5 февраля 2024 г. 1:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 10:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 8:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 декабря 2023 г. 21:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
a
a_vlasov14 апреля 2024 г. 6:41
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел Дорофеев14 апреля 2024 г. 2:35
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrex4 апреля 2024 г. 4:47
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
P
Pisych27 февраля 2023 г. 4:04
Как получить в массив значения из связанной модели? Спасибо, разобрался:))
AC
Alexandru Codreanu19 января 2024 г. 11:57
QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…

Следите за нами в социальных сетях