添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
logo logo

将 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);