将 Web 前端嵌入 QT
QT 技术分享
Apr 25, 2020 · 10min
Note: 这是一篇我从整理箱中找出来的过去的文章,所以一些技术细节可能与当下不符合,请阅读者自行判断。
前置知识: 基础的 QT 开发经验,前端工程化 (Nodejs, npm...)
由于工作上的关系,我会接触到 QT 开发。作为跨平台的客户端开发框架,QT 有非常好的性能优势,但是对于 UI/UX 部分,开发 QT 则需要强大的审美,以及面临大部分控件都必须自己开发的巨大压力。于是我尝试着将生态丰富的 Web 技术引入 QT 中。
# QT 的 Web 容器
QT 和其他技术的混合开发一样,为了嵌入 Web 页面,QT 提供一个所谓的“容器”,用来“容纳” Web 页面。目前的 QT 版本中,过去的 Qt WebView 已经被 Qt WebEngine 替代。Qt WebEngine 提供了一个 Web 引擎,可以在 QT 中嵌入 Web 页面。Qt WebEngine 的背后,正是我们熟悉而又陌生的朋友 Chromium 。
对于 Web 嵌入来说,主要是需要理解 JS 是如何和 C++(QT) 完成双向通信的。QT 为我们提供了一个 QWebChannel 的通信管道。本文中,我们暂时不讨论 QWebChannel 的具体实现,我们只需要考虑如何使用这个通信管道完成 JS 和 C++(QT) 的通信。
# Javascript 调用 C++ 方法
首先,我们需要在 QT 中定义一个类,该类包含了一个插槽函数,回头这个插槽函数可以供 JS 调用:
class WebObj : public QObject
Q_OBJECT
public slots:
QString sendToQT(QString strParameter)
QMessageBox::information(NULL, strParameter);
return "Hi, JS, I'm QT";
WebObj *webObj = new WebObj();
QWebChannel *channel = new QWebChannel(this);
channel->registerObject("webObj", webObj);
view->page()->setWebChannel(channel);
在 JS 这边,QT 官方为我们提供了一个
qwebchannel.js
,它提供了一个
QWebChannel
类,该类允许你初始化一个通信管道,然后获取到 QT 侧提供的一些信息和方法。
QWebChannel
接收两个参数,第一个参数是 QT 利用 Qt WebEngine 挂载载前端全局环境中的
window.qt.webChannelTransport
,另外一个参数是一个回调函数,该回调函数在
QWebChannel
完成初始化后调用:
new QWebChannel(qt.webChannelTransport, (channel) => {
window.webObj = channel.objects.webObj
然后,我们就可以在 JS 侧愉快的使用 C++ 中使用的方法了:
const result = window.webObj.sendToQT('Hello, QT, I\'m JS')
console.log(result) // Hi, JS, I'm QT
# C++ 传递数据给 Javascript
我们可以通过信号的方式将数据从 C++ 传递给 JS,在 C++ 这边,我们需要定义一个信号,然后让 JS 监听这个信号,当 C++ 侧触发这个信号,并通过这个信号传递数据时,JS 侧通过事先准备的回调函数来接收这些数据:
// C++ 这里定义信号
class WebObj : public QObject
Q_OBJECT
public slots:
QString sendToQT(QString strParameter)
QMessageBox::information(NULL, strParameter);
return "Hi, JS, I'm QT";
void sendToJS(QString strParameter)
emit someThingChange(strParameter);
signals:
void someThingChange(QString strParameter);