如何捕捉和处理 QWebEnginePage 内容变化?

Posted

技术标签:

【中文标题】如何捕捉和处理 QWebEnginePage 内容变化?【英文标题】:How to catch and handle QtWebEnginePage content changing? 【发布时间】:2017-01-31 20:23:24 【问题描述】:

在 Qt 的 (现已弃用) QWebPage 类中,每当网页的 html 内容被以下任一者更改时,都会调用一个信号 contentsChanged()用户编辑页面或以编程方式更改的页面。在较新的QtWebEnginePage 类中似乎没有等效信号。鉴于从 Qt 应用程序使网页可编辑的方法已从 QWebPage::setContentEditable 方法更改为原生 html5 javascript contenteditable,这并不让我感到惊讶。

我的问题: 有没有办法“倾听”QtWebEnginePage 内容的变化?这是我现在必须以某种方式从 javascript 处理的东西吗?

请注意,我查看了 Qt 提供的移植信息,但没有发现任何让我印象深刻的相关信息...

【问题讨论】:

【参考方案1】:

不幸的是,QtWebEngine 与其他 Qt 工具的集成比QtWebKit 更差。 QtWebKit 能够开箱即用的许多事情只能通过 QtWebEngine 的 JavaScript 诡计才能实现。我能够在自己的项目中解决这个特殊问题,但这并不容易。

首先,我必须通过QWebChannel 设置C++ 代码和JavaScript 代码之间的交互。在这个答案中涵盖的主题太大,但从好的方面来说,这方面的文档或多或少都不错:请参阅Qt WebChannel JavaScript API 及其examples。最后从 C++ 代码你应该能够做类似的事情

webChannel->registerObject(QStringLiteral("myObject"), myObject);

其中webChannel 是指向QWebChannel 的指针,myObject 是指向具有公共槽的QObject 子类的指针。此操作将允许 JavaScript 代码调用 myObject 的公共槽,从而实现 JavaScript 和 C++ 之间的连接。

JavaScript 用于跟踪 DOM 变化的“原生”解决方案是MutationObserver。它是一个实例化的 JavaScript 对象,用于监听 DOM 变化。在每个 DOM 突变上,观察者调用在构造时提供给它的回调函数。为了通知 C++ 代码 DOM 的变化,回调应该调用一些暴露给 JavaScript 的对象的槽。在此插槽内的 C++ 代码中,您可以随意对内容更改做出反应 - 如果 C++ 代码的多个部分可能想要订阅 contentsChanged 信号,请为它们提供这样的信号,从 @ 的插槽发出987654336@.

这是一个在 JavaScript 端设置 MutationObserver 的简单示例:

var observer = MutationObserver(function(mutations, observer) 
    myObject.onContentChanged();
);

observer.start = function() 
    this.observe(document, 
        subtree: true,
        attributes: true,
        childList: true,
        characterData: true,
        characterDataOldValue: true
    );


observer.stop = function() 
    this.disconnect();

虽然这种方法的设置比使用QtWebKitcontentsChanged 信号要复杂得多,但最终我发现它更加灵活,因为使用MutationObserver 你可以看到正是在DOM中发生了变化并进行了一些高级处理:

    忽略您不感兴趣的更改。 记住之前的 DOM 状态,以便进一步实现撤消/重做。 当您手动执行的 JavaScript 代码需要更改 DOM 时,暂停监听 DOM 更改 - 有时,通知 C++ 代码此类更改很方便,因为 C++ 代码很难区分在文本编辑引起的变化和某些脚本执行引起的变化之间。 记录确切发生的更改 - 是否添加、删除或更改了某个节点等。

【讨论】:

以上是关于如何捕捉和处理 QWebEnginePage 内容变化?的主要内容,如果未能解决你的问题,请参考以下文章

QWebEnginePage.print 与 QPrintPreviewDialog 导致空预览

QWebEnginePage 中的 setFeaturePermission 成员函数如何工作?

如何捕获 QWebEnginePage::view 渲染的图像?

Python - 如何在 QWebEnginePage 中使用 mainframe() 方法 [mainframe() 错误]

qt5.7 中的信号和槽 - QWebEnginePage

QWebEnginePage:toHtml 返回一个空字符串