Как определить собственные JS-функции при работе с QJSEngine от PySide6

В инструкции рассмотрим как определять пользовательские JavaScript-функции для QJSEngine от PySide6 в программах на Python

1 мин на чтение

Наличие в Qt движка языка JavaScript открывает широкие возможности по расширению програмных систем. В инструкции ниже рассмотрим как определять пользовательские JavaScript-функции для QJSEngine от PySide6 в программах на Python.

Основная идея заключается в создании класса-наследника от QObject и определении в этом классе необходимых функций. Далее экземпляр класса и его функции регистрируются в QJSEngine. После этого функции могут быть вызваны из JavaScript-скриптов, подаваемых в метод QJSEngine.evaluate().

На самом деле в сети масса примеров решения этой задачи на Qt C++. При этом для Qt Python (PySide) информации очень мало. Главная проблема, с которой пришлось столкнуться, это чем в Python заменить макрос Q_INVOKABLE из C++. Выяснилось, что достаточно аннотировать методы как слоты (@Slot()). Остальное - дело техники: все вызовы практически полностью соответствуют примерам на С++.

Полный скрипт qjsengine_in_pyside_example.py на Python:

from PySide6.QtCore import QCoreApplication, QObject, Slot
from PySide6.QtQml import QJSEngine


# Define class with invokable methods
class MyObject(QObject):
    def __init__(self, parent = None):
        super().__init__(parent)

    @Slot()
    def print_start(self):
        print("Start")

    @Slot(result=int)
    def get_integer(self):
        return 33
    
    @Slot(int)
    def print_integer(self, value):
        print("Integer is", value)

    @Slot()
    def print_finish(self):
        print("Finish")


# Create application and JS engine
app = QCoreApplication()
engine = QJSEngine()

# Create MyObject instance and declare it in the JS engine
my_object = MyObject()
my_object_js = engine.newQObject(my_object)

# Define JS functions based on the MyObject methods
engine.globalObject().setProperty("printStart", my_object_js.property("print_start"))
engine.globalObject().setProperty("getInteger", my_object_js.property("get_integer"))
engine.globalObject().setProperty("printInteger", my_object_js.property("print_integer"))
engine.globalObject().setProperty("printFinish", my_object_js.property("print_finish"))

# Read JS script
script = open("test.js", "r").read()

# Run JS script
res = engine.evaluate(script)

Файл test.js с JS-скриптом для теста программы:

printStart();
var i = getInteger();
printInteger(i);
printFinish();

Запуск программы (файлы qjsengine_in_pyside_example.py и test.js должны находиться в одной директории):

> python qjsengine_in_pyside_example.py
Start
Integer is 33
Finish

Файлы с исходным кодом можно найти на GitHub Gists.


Обсудить в Телеграм


Свежие записи

Как разбить проект CMake на подпроекты

Как разбить проект CMake на подпроекты

Разделяем на подпроекты существующий проект C++ на CMake

1 мин на чтение

Как создать оконное приложение на Qt в среде QtCreator

Как создать оконное приложение на Qt в среде QtCreator

Учимся создавать свое первое оконное приложение на Qt с использованием QMainWindow в среде QtCreator

6 мин на чтение

Как создать 3D модель с помощью OpenCASCADE на C++ в среде QtCreator

Как создать 3D модель с помощью OpenCASCADE на C++ в среде QtCreator

Учимся создавать свою первую 3D модель тора в OpenCASCADE

3 мин на чтение

Как работать с пул-реквестами в личном репозитории GitHub

Как работать с пул-реквестами в личном репозитории GitHub

Учимся работать с пул-реквестами на GitHub в личных репозиториях

3 мин на чтение

Как исследовать exe-файлы с Cutter. Практика обратной разработки

Как исследовать exe-файлы с Cutter. Практика обратной разработки

Простейший пример исследования и патчинга исполняемого файла с помощью Cutter

2 мин на чтение