Como chegar Javascript em um QWebView para criar novas instâncias de classes com base C ++?
-
09-09-2019 - |
Pergunta
Eu adicionei com sucesso um objeto C ++ a um QWebFrame com addToJavaScriptWindowObject , e pode chamar um slot nesse objeto de javascript.
Mas o que eu realmente quero fazer é ter um desses slots de retornar um novo objeto. Por exemplo, eu tenho um slot como este, que retorna um QObject derivado instância de classe:
MyObject* MyApp::helloWorld()
{
//MyObject is dervied from QObject
return new MyObject();
}
Eu posso chamar esse slot de javascript com sucesso como esta ??p>
var foo=myapp.helloWorld();
mas parece foo estar vazio, não pode chamar qualquer slots ou o acesso de qualquer Propriedades nele de JavaScript.
Algumas ideias sobre como eu posso conseguir isso?
Solução
Um corte feio Eu considerei é usar addToJavaScriptWindowObject para soltar o objeto Quero voltar para o objeto janela com um nome aleatório, então tenho a minha abertura de retorno o nome da instância do objeto em vez disso:
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;
}
A JS pode ser escrito para verificar se o valor de retorno é uma string, e se for, pegue o objeto da janela:.
var foo=myapp.helloWorld();
if (typeof foo == "string")
{
foo=window[foo];
}
Um pouco feio, mas vai ter me por até um método melhor vem junto. Futuras versões do Qt vão unificar os scripting apoio para que tudo é baseado no JavaScriptCore no WebKit, por isso espero que isso vai melhorar, então!
Outras dicas
Você pode atribuir o ponteiro de objeto para um QObject * e retornar isso.
QObject * obj = new MyObject();
return obj;
Isso está funcionando para mim na porta Qt Webkit no Linux.
QtScript tem a noção de protótipos - que lhe permite criar um C ++ protótipo para um valor script. Estamos investigando wether podemos colmatar QtScript com JavaScriptCore - que deve resultado na possibilidade de usar protótipos de ambiente JavaScript do WebKit também; http://doc.trolltech.com/ 4,5 / qtscript.html # tornando-based-use-of-protótipo-herança
Tente devolver o novo objeto como um QObject * em vez de um MyObject *. Se você está apenas trabalhando com QtScript, então você pode chamar qScriptRegisterMetaType para definir algum código para lidar com conversão de MyObject * s em QScriptValues ??(ou QVariants), mas não parece ser um equivalente para o motor JavaScript utilizada em QtWebKit.
Irritantemente, isso significa que expor o seu modelo de objeto interno para WebKit deve envolver quer ter um conjunto separado de funções de proxy que convertem seus ponteiros de objeto para QObject * s, ou usando classes de adaptador de algum tipo para fazer a mesma coisa.
Esta resposta é baseada na resposta de Paulo, mas um pouco simplificado. Testado e funcionando para o Qt 5.3. Você precisa de uma fábrica que instancia um objeto e, em seguida, retorna um ponteiro QObject
a este objeto. classe do objeto deve herdar a partir QObject
para que ele funcione corretamente em JavaScript:
QObject * MyApp::createInstance(QString objname) {
MyClass * obj = new MyClass(this);
m_mainWindow->webView->page()->mainFrame()->addToJavaScriptWindowObject(objname, obj, QWebFrame::ScriptOwnership);
return obj;
}
Com isso, você pode fazer o seguinte a partir de Javascript:
var myobject = MyApp.createInstance("obj1");
Neste ponto, você tem obj1
, bem como myobject
no espaço global JavaScript (eles são apenas ponteiros, assim fazendo ambas as seguintes obras:
myobject.testmethod();
obj1.testmethod();
Neste ponto, você pode usar connect
em JavaScript para conectar sinais de C ++ para ranhuras JavaScript. Mais informações sobre esta técnica aqui: http://doc.qt.io/qt- 5 / QtWebKit-bridge.html