2009-06-03 17 views
6

Ho aggiunto con successo un oggetto C++ a un QWebFrame con addToJavaScriptWindowObject, e posso richiamare uno slot su quell'oggetto da javascript.Come ottenere Javascript in un QWebView per creare nuove istanze di classi basate su C++?

Ma quello che voglio veramente fare è che uno di questi slot restituisca un nuovo oggetto. Ad esempio, ho uno slot come questo, che restituisce un'istanza di classe QObject derivata:

MyObject* MyApp::helloWorld() 
    { 
      //MyObject is dervied from QObject 
      return new MyObject(); 
    } 

posso chiamare questo slot da javascript con successo come questo

var foo=myapp.helloWorld(); 

Ma foo sembra essere vuoto, ho non è possibile chiamare nessuno slot o accedere a qualsiasi proprietà di su di esso da Javascript.

Qualche idea su come posso raggiungere questo obiettivo?

+0

Nella domanda intendete MyApp :: helloWorld, giusto? – jrharshath

+0

Sì, ben chiazzato :) –

risposta

4

uno piuttosto brutto hack che ho considerato è quello di utilizzare addToJavaScriptWindowObject far cadere l'oggetto voglio tornare nell'oggetto finestra con un nome casuale, quindi avere il mio slot per restituire il nome dell'istanza oggetto invece:

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; 
} 

I JS possono essere scritti per verificare se il valore di ritorno è una stringa, e se lo è, afferrare l'oggetto dalla finestra .:

var foo=myapp.helloWorld(); 
if (typeof foo == "string") 
{ 
    foo=window[foo]; 
} 

un po 'brutto, ma avranno da me fino ad una migliore il metodo arriva. Le future versioni di Qt stanno unificando il supporto per lo scripting in modo che tutto sia basato su JavaScriptCore in WebKit, quindi speriamo che questo migliorerà!

1

QtScript ha la nozione di prototipi, che consente di creare un prototipo C++ per un valore di script. Stiamo investigando se possiamo collegare QtScript con JavaScriptCore - che dovrebbe provocare la possibilità di utilizzare prototipi anche dall'ambiente JavaScript di WebKit; http://doc.trolltech.com/4.5/qtscript.html#making-use-of-prototype-based-inheritance

+0

Sì, ho visto che un po 'di unificazione è sulla tabella di marcia, che sarebbe bello. Ho comunque tirato fuori per nascondere la "bruttezza" della mia soluzione, quindi il js che scrivo rimarrà in gran parte utilizzabile quando si presenteranno soluzioni migliori. –

1

Provare a restituire il nuovo oggetto come oggetto QObject * anziché come oggetto MyObject *. Se si sta solo lavorando con QtScript, è possibile chiamare qScriptRegisterMetaType per definire un codice per la gestione della conversione di MyObject * s in QScriptValues ​​(o QVariants), ma non sembra essere equivalente al motore JavaScript utilizzato in QtWebKit.

Sorprendentemente, ciò significa che l'esposizione del proprio modello di oggetto interno a WebKit comporta l'utilizzo di un set separato di funzioni proxy che convertono i puntatori oggetto in QObject * s, o utilizzando classi di adattatore di qualche tipo per fare la stessa cosa.

+0

In effetti, quello che mi ha lasciato sono le classi di adattatori in C++ e JS per colmare il divario e lasciare che il "vero" JS si senta come se tutto accadesse come dovrebbe. –

2

È possibile assegnare il puntatore dell'oggetto a un oggetto QO * e restituirlo.

Questo funziona per me sulla porta Qt Webkit su Linux.

0

Questa risposta è basata sulla risposta di Paolo, ma un po 'semplificata. Testato e funzionante per Qt 5.3. È necessario un factory che istanzia un oggetto e quindi restituisce un puntatore QObject a questo oggetto.classe dell'oggetto deve ereditare da QObject in modo che funzioni correttamente in JavaScript:

QObject * MyApp::createInstance(QString objname) { 
    MyClass * obj = new MyClass(this); 
    m_mainWindow->webView->page()->mainFrame()->addToJavaScriptWindowObject(objname, obj, QWebFrame::ScriptOwnership); 
    return obj; 
} 

Con questo, è possibile effettuare le seguenti operazioni da JavaScript:

var myobject = MyApp.createInstance("obj1"); 

A questo punto, avete obj1 pure come myobject nel namespace globale JavaScript (sono solo puntatori, così facendo entrambe le seguenti opere:

myobject.testmethod(); 
obj1.testmethod(); 

a questo punto, è possibile utilizzare connect in JavaScript per collegare i segnali C++ agli slot JavaScript. Maggiori informazioni su questa tecnica qui: http://doc.qt.io/qt-5/qtwebkit-bridge.html