NOTE: This library inherits from private Qt modules. Use with caution.
A simple Qt widget for embedding a web view without the need for Quick or WebEngine.
Why embed Blink or WebKit when the host already has a browser engine?
Qt comes with a web view QML widget out of the box, but you are mostly limited to interacting with it in the QML context. The developers of Qt don't seem to think anyone would want to do things like call runJavaScript
from C++.
So I came up with this widget that just does one thing, which is embed a web view through C++ and supports things like executing JavaScript with callbacks. The widget currently still uses the underlying components of QtWebView by reaching into its protected/private members, making this library very small.
- Qt >= 6.x
- qmake
git clone https://github.com/ravenstine/qt-web-view-widget.git
cd qt-web-view-widget
qmake
make
make install
This will create a dist/
folder with a lib
and include
path. You can leave this in place or copy the files wherever they need to go on your system. I don't really want to bother handling individual install paths for different operating systems.
If you are using Qt Creator, you can right-click on the name of your project in the Projects pane and select Add Library. Choose External Library, select the .o
/.so
/.a
/.dylib
/.dll
file, and make sure to specify the include/
directory path for the headers.
You can do the same thing manually in your .pro
file, depending on where you compiled the library, with something like this:
LIBS += -L$$PWD/../qt-web-view-widget/dist/lib/ -lwebviewwidget
INCLUDEPATH += $$PWD/../qt-web-view-widget/dist/include
DEPENDPATH += $$PWD/../qt-web-view-widget/dist/include
Also make sure you have the following:
QT += widgets webview-private
You can now include the library in your C++ code:
#include <qtwebviewwidget/widget.h>
The class WebViewWidget
will then be available for you to use.
Inherits from QWidget
Use this widget to instantiate a web view using the available browser engine on the host. The view will fill the entire space of the widget and resize with it.
Example:
#include <QApplication>
#include <QMainWindow>
#include <QDebug>
#include <qtwebviewwidget/widget.h>
QT_USE_NAMESPACE
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QMainWindow window;
WebViewWidget webViewWidget(QUrl(QString("https://www.qt.io/")));
window.setCentralWidget(&webViewWidget);
window.show();
return app.exec();
}
Most of the methods you'll be using for interacting with the web context are on the webView
member.
This inserts the WebView into the widget's internal window and initializes it. It is called automatically when the widget is inserted.
The widget waits until it insertion to initialize the view to prevent it from doing things like navigate and fire off requests before the developer has fully configured it. However, this usually causes a slight delay between the Qt app rendering on screen and the web view actually being visible.
If you want the web view to appear at the same time as the app, call init()
to kick off invoking the web view before the app is painted.
This class is primarily a derivative of the private QWebView
C++ class but elevates it to being public. It is nearly the same as the QML WebView widget, the API of which you can read about here, but with more methods exposed including a few slight modifications to make it more useful outside of a QML context.
The reason this is a separate class from WebViewWidget
is so that you can integrate a web view in other contexts besides a widget.
In summary, you will get a lot of the basic functions of working with a web browser, but there are no native ways to listen to events or intercept requests, although those things are theoretically possible by emulating it with injected JavaScript. The reason why things like QtWebEngine exists is to overcome these issues and improve consistency across platforms.
I don't know precisely what this is supposed to do, but it's there because it might be used to initialize something for the host web view browser engine.
The runJavaScript
method is nearly the same as the one exposed within the QML JavaScript engine, except you can use it in C++ and pass a function pointer or lambda as a callback that will be performed when the provided script is finished performing.
Example:
#include <QApplication>
#include <QMainWindow>
#include <QDebug>
#include <qtwebviewwidget/widget.h>
QT_USE_NAMESPACE
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QMainWindow window;
WebViewWidget webViewWidget(QUrl(QString("https://www.qt.io/")));
window.setCentralWidget(&webViewWidget);
webViewWidget.webView->runJavaScript("'foobar';", [&] (const QVariant &result) {
qDebug() << result.toString();
});
window.show();
return app.exec();
}
Although not stated in the official documentation, the WebView
does support other signals that can be useful for responding to page state.
See [https://doc.qt.io/qt-6/qml-qtwebview-webview.html#loadingChanged-signal](loadingChanged signal).
Example:
#include <QApplication>
#include <QMainWindow>
#include <QDebug>
#include <QObject>
#include <qtwebviewwidget/widget.h>
QT_USE_NAMESPACE
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QMainWindow window;
WebViewWidget webViewWidget(QUrl(QString("https://www.qt.io/")));
window.setCentralWidget(&webViewWidget);
QObject::connect(webViewWidget.webView, &WebView::loadingChanged, [] (const WebViewLoadRequest &loadRequest) {
qDebug() << &loadRequest;
});
window.show();
return app.exec();
}
WebViewLoadRequest
is just a public alias for QWebViewLoadRequestPrivate
.
This is a low-level signal method, you probably don't want to use it, but it's there.
See LICENSE.txt