QWebChannel - js: Uncaught ReferenceError: qt is not defined
-
I am trying to migrate to QtWebEngine all my code that is using QWebKit.
in my .cpp code:
QWebChannel *channel = new QWebChannel(ui->webView_workouts->page()); ui->webView_workouts->page()->setWebChannel(channel); channel->registerObject(QString("workoutObject"), this);
In my webpage: (qwebchannel.js is loaded the header of the page)
var workoutObject; new QWebChannel(qt.webChannelTransport, function (channel) { // now you retrieve your object workoutObject = channel.objects.workoutObject; });
I am getting this error :
js: Uncaught ReferenceError: qt is not defined
When I try to use "workoutObject" in the js, since it is not loaded correctly I get:
js: Uncaught TypeError: Cannot read property 'filterChanged' of undefinedAny help appreciated, currently stuck to migrate with QWebEngine..
-
I tried to debug in the webpage and qt is always undefined for some reason?
I am using latest Qt 5.7.0 on MSVC 2015
var workoutObject; if (typeof qt != 'undefined') { alert("Qt is OK!!"); new QWebChannel(qt.webChannelTransport, function (channel) { // now you retrieve your object workoutObject = channel.objects.workoutObject; }); } else { alert("Qt is not defined!"); }
-
I copied the whole content of qwebchannel.js inside my page just before "new QWebChannel..." and I do not get the error on the Qtcreator console, but still qt is undefined (get the alert message on my webpage).
Also to note that I try to set my channel after the page is loaded, and it get triggered 2 times? I only load the URL once. I read on other forums that reloading the page could stop the channel from working, but I am unable to make it work in the first place.
ui->webView_workouts->load(QUrl(Environnement::getUrlWorkout())); connect(ui->webView_workouts->page(), SIGNAL(loadFinished(bool)), this, SLOT(connectToJs(bool))); void Main_WorkoutPage::connectToJs(bool result) { qDebug() << "connectToJs!" << result; if (result) { QWebChannel *channel = new QWebChannel(ui->webView_workouts->page()); ui->webView_workouts->page()->setWebChannel(channel); channel->registerObject(QString("workoutObject"), this); } }
-
Hi,
I haven't played with QtWebChannel yet but did you get the QtWebChannel Standalone Example to run ? That might give you some hints to go further.
Hope it helps
-
@maximus
can you show how you include the qwebchannel.js into your page.
Are you using a custom HTML page? or are you loading a page? -
@maximus
Here is a way to include the webchannel stuff without worrying anymore:QWebEngineProfile* profile = new QWebEngineProfile("MyWebChannelProfile", parent); QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js"); if( !webChannelJsFile.open(QIODevice::ReadOnly) ) { qFatal( QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString()) ); } else { QByteArray webChannelJs = webChannelJsFile.readAll(); webChannelJs.append( "\n" "new QWebChannel(qt.webChannelTransport, function(channel) {" " workoutObject = channel.objects.workoutObject;" "});" ); QWebEngineScript script; script.setSourceCode(webChannelJs); script.setName("qwebchannel.js"); script.setWorldId(QWebEngineScript::MainWorld); script.setInjectionPoint(QWebEngineScript::DocumentCreation); script.setRunsOnSubFrames(false); profile->scripts()->insert(script); }
Then make sure you create a QWebEnginePage with the profile on your view:
new QWebEnginePage(profile,view)
-
hey @raven-worx, thanks for the reply
I am using a custom html page that I control.
The .js file is loaded this way:
<script type="text/javascript" src="http://localhost/assets/js/qwebchannel.js"></script>
I then have another <script> section at the end of my page that is creating a QWebChannel
I can access the page source and click on the link fine to see the js file.Also note that I am using Designer to create my QWebEngineView so object is already instantiated in my .cpp
I'll try loading it your way and post my result soon.
Thanks -
You are a lifesaver, it worked this way! Now to figure out how to strip and put this code generic because I use around 10 QWebEngineView :)
QWebEngineProfile *profile = new QWebEngineProfile("MyWebChannelProfile", this); QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js"); if( !webChannelJsFile.open(QIODevice::ReadOnly) ) { qDebug() << QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString()); } else { qDebug() << "OK webEngineProfile"; QByteArray webChannelJs = webChannelJsFile.readAll(); webChannelJs.append( "\n" "var workoutobject" "\n" "new QWebChannel(qt.webChannelTransport, function(channel) {" " workoutobject = channel.objects.workoutobject;" "});" ); QWebEngineScript script; script.setSourceCode(webChannelJs); script.setName("qwebchannel.js"); script.setWorldId(QWebEngineScript::MainWorld); script.setInjectionPoint(QWebEngineScript::DocumentCreation); script.setRunsOnSubFrames(false); profile->scripts()->insert(script); } QWebEnginePage *myPage = new QWebEnginePage(profile, ui->webView_workouts); ui->webView_workouts->setPage(myPage); QWebChannel *channel = new QWebChannel(myPage); ui->webView_workouts->page()->setWebChannel(channel); channel->registerObject("workoutobject", this); ui->webView_workouts->load(QUrl(Environnement::getUrlWorkout()));
And now my .js page doesn't have anything related to Qt, really clean result.
Thanks a lot
Max -
I am running into problem using profile->scripts()->insert(script);
There is conflict with multiple scripts that I insert in my shared QWebEngineProfile.
I use the same QWebEngineProfile on all my webpage in my application in order to keep cookie data, etc.So when I insert a new script, it overwrite the last one inserted and screw up my QWebChannel initialization
Resulting in warning like "js: Uncaught ReferenceError: zoneObject is not defined"
Trying to find a solution..
script.setWorldId(QWebEngineScript::MainWorld); maybe set a unique worldID for each page but that doesnt seem to work now -
Solution found, insert the script to the page instead of the profile
void WorkoutCreator::createWebChannel() { QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js"); if( !webChannelJsFile.open(QIODevice::ReadOnly) ) { qDebug() << QString("Couldn't open qwebchannel.js file: %1").arg(webChannelJsFile.errorString()); } else { qDebug() << "OK webEngineProfile"; QByteArray webChannelJs = webChannelJsFile.readAll(); webChannelJs.append( "\n" "var workoutCreator" "\n" "new QWebChannel(qt.webChannelTransport, function(channel) {" " workoutCreator = channel.objects.workoutCreator;" "});" "\n" "function enableSaveButton(forceOff) {" "if (forceOff) {$('#btn-save-workout').prop('disabled', true);return;}" "var nameValue = $('#name-workout').val();" "var planValue = $('#plan-workout').val();" "var creatorValue = $('#creator-workout').val();" "if (nameValue.length > 0 && creatorValue.length > 0 && planValue.length > 0) {$('#btn-save-workout').prop('disabled', false);}" "else {$('#btn-save-workout').prop('disabled', true);}" "}" ); QWebEngineScript script; script.setSourceCode(webChannelJs); script.setName("qwebchannel.js"); script.setWorldId(QWebEngineScript::MainWorld); script.setInjectionPoint(QWebEngineScript::DocumentCreation); script.setRunsOnSubFrames(false); // profile->scripts()->insert(script); QWebEnginePage *myPage = new QWebEnginePage(profile, ui->webView_createWorkout); ui->webView_createWorkout->setPage(myPage); myPage->scripts().insert(script); QWebChannel *channel = new QWebChannel(myPage); ui->webView_createWorkout->page()->setWebChannel(channel); channel->registerObject("workoutCreator", this); } }
-
call page()->setWebChannel() before QWebEngineView::load()
==>
.......
QWebChannel *channel = new QWebChannel(ui->webView_workouts->page());
ui->webView_workouts->page()->setWebChannel(channel);
channel->registerObject(QString("workoutObject"), this);
......
ui->webView_workouts->load(QUrl(Environnement::getUrlWorkout()));
.......