Как получить Javascript в QWebView для создания новых экземпляров классов на основе C ++?
-
09-09-2019 - |
Вопрос
Я успешно добавил объект C ++ в QWebFrame с addToJavaScriptWindowObject Добавить javascriptwindowobject, и может вызывать слот для этого объекта из javascript.
Но что я действительно хочу сделать, так это чтобы один из этих слотов возвращал новый объект.Например, у меня есть такой слот, который возвращает экземпляр производного класса QObject:
MyObject* MyApp::helloWorld()
{
//MyObject is dervied from QObject
return new MyObject();
}
Я могу успешно вызвать этот слот из javascript следующим образом
var foo=myapp.helloWorld();
Но foo кажется пустым, я не могу вызвать какие-либо слоты или получить доступ к каким-либо свойствам на нем из Javascript.
Есть какие-нибудь идеи о том, как я могу этого добиться?
Решение
Я рассмотрел один довольно уродливый хак: использовать addToJavaScriptWindowObject для удаления объекта, который я хочу вернуть, в объект окна со случайным именем, а затем заставить мой слот вместо этого возвращать имя экземпляра объекта:
QString MyApp::helloWorld()
{
//general a unique name for the js variable
QString name=getRandomVariableName();
//here's the object we want to expose to js
MyObject* pReturn=new MyObject();
//we make attach our object to the js window object
getWebFrame()->addToJavaScriptWindowObject(name, pReturn,
QScriptEngine::ScriptOwnership);
//tell js the name we used
return name;
}
JS можно написать так, чтобы проверять, является ли возвращаемое значение строкой, и если да, то захватывать объект из окна:
var foo=myapp.helloWorld();
if (typeof foo == "string")
{
foo=window[foo];
}
Немного некрасиво, но поможет мне, пока не появится лучший метод.В будущих версиях Qt поддержка сценариев будет унифицирована, и все они будут основаны на JavaScriptCore в WebKit, так что, надеюсь, тогда ситуация улучшится!
Другие советы
Вы можете назначить указатель объекта на QObject * и вернуть его.
QObject * obj = new MyObject();
return obj;
У меня это работает над портом Qt Webkit в Linux.
В QtScript есть понятие прототипов, которое позволяет вам создавать прототип C++ для значения скрипта.Мы изучаем, сможем ли мы соединить QtScript с JavaScriptCore, что должен результатом также является возможность использования прототипов из среды JavaScript WebKit; http://doc.trolltech.com/4.5/qtscript.html#making-use-of-prototype-based-inheritance
Попробуйте вернуть ваш новый объект как QObject *, а не как MyObject *.Если вы просто работаете с QtScript, то вы можете вызвать Qscriptregisterметатип определить некоторый код для обработки преобразования MyObject * ов в QScriptValues (или QVariants), но, похоже, нет эквивалента для движка JavaScript, используемого в QtWebKit.
Досадно, но это означает, что предоставление вашей внутренней объектной модели WebKit потребует либо наличия отдельного набора прокси-функций, которые преобразуют указатели ваших объектов в QObject * ы, либо использования каких-либо классов адаптеров для выполнения того же самого.
Этот ответ основан на ответе Пола, но немного упрощен.Протестировано и работает на Qt 5.3.Вам нужна фабрика, которая создает экземпляр объекта, а затем возвращает QObject
указатель на этот объект.Класс объекта должен наследовать от QObject
чтобы он правильно работал в JavaScript:
QObject * MyApp::createInstance(QString objname) {
MyClass * obj = new MyClass(this);
m_mainWindow->webView->page()->mainFrame()->addToJavaScriptWindowObject(objname, obj, QWebFrame::ScriptOwnership);
return obj;
}
Благодаря этому вы можете сделать следующее из Javascript:
var myobject = MyApp.createInstance("obj1");
На данный момент у вас есть obj1
а также myobject
в глобальном пространстве имен JavaScript (это просто указатели, поэтому выполняются оба следующих действия:
myobject.testmethod();
obj1.testmethod();
На этом этапе вы можете использовать connect
в JavaScript для подключения сигналов C++ к слотам JavaScript.Дополнительная информация об этой технике здесь: http://doc.qt.io/qt-5/qtwebkit-bridge.html