QWebView set内容在单独的线程中



我有一个应用程序需要使用QWebView::setContent()将一些HTML内容加载到QWebView。所有这些都发生在带有ARMv5处理器(想想400 MHz(的嵌入式设备上。大多数情况下,我可以在合理的时间内(最多 5 秒(加载页面,但有时我的内容需要很长时间才能加载(30KB 的内容需要 ~30 秒(。

问题是setContent调用阻塞了主线程。我需要能够在加载期间处理事件,如果用户决定不再等待,我甚至可以取消加载。

我正在考虑在其他线程中运行 setContent 调用,这样它就不会阻塞事件处理,如有必要,我可以取消它。但是,我得到了可怕的"必须在 GUI 线程中创建小部件",我认为没有办法轻松解决这个问题。

是否可以在单独的线程中运行QWebView::setContent?如果是这样,如何?如果不是,是否可以在setContent运行时处理 GUI 事件?是否可以"取消"setContent通话?

编辑

为了澄清更多,我真正感兴趣的是如何能够停止setContent调用和/或处理 GUI 消息,以便界面保持响应,使用 setContent 传递大量数据。

编辑 2

为了进一步澄清,我正在处理长而静态的内容,即没有JavaScript,只有大量的静态HTML,即使加载更多内容,用户也希望通过这些内容滚动。主要思想是允许她/他进入页面,即使页面没有完全加载。

前段时间我遇到了类似的问题。据我所知,只有页面的主要内容是同步运行的。

事实是 GUI 核心"绘制"页面,这很耗时。因此,主线程被冻结,直到主要内容完全加载。

就我而言,解决方案很简单:使主要内容成为次要内容并使用本地文件!!

那么,我的建议是什么:

1( 准备一个包含以下内容的本地文件 ( /tmp/loader.html (:

<html>
<body onload='setTimeout(function() { window.location="contents.html"; }, 1000);'>
Loading...
</body>
</html>

2(每次需要加载新内容时,将其保存到辅助文件(/tmp/contents.html(并强制更新加载程序(也可能是刷新(。容易:

QFile f("/tmp/contents.html");
if (f.open(QFile::WriteOnly)) {
    qint64 pos = 0;
    while (pos < contents.length()) {
        pos += f.write(contents.mid(pos, 1024)); // chunk of 1024
        qApp->processEvents();
    }
    f.close();
    webview->setUrl(QUrl::fromLocalFile("/tmp/loader.html"));
}

观察我允许事件循环处理挂起的事件,如果文件保存也很慢......

3(每当您需要取消加载时,都可以加载其他内容,删除内容文件或其他可能的方法。

请注意,据我所知,您永远不会异步绘制内容。这才是嵌入式系统中真正的问题。

由于QWebView::setContent()是一个阻塞调用,我最终使用了解决方法。主要思想是 XML 处理比呈现页面快得多。因此,我执行以下操作:

  1. 将文档解析为 XML DOM 文档(在我的情况下是一个合理的假设(,并找到 body 元素。
  2. 仅保留预定义数量的body子元素(大约 20 个元素(。将其余元素存储在另一个 XML DOM 文档中。
  3. 使用 QWebView::setContent() 显示初始文档(序列化 XML(,相对较快。在 SLOT(loadNextChunk()) 上启动超时为 0 的计时器。
  4. loadNextChunk()使用 body->appendInside(html) 从正文末尾的备份文档中移动另外 20 个左右的元素,其中 body 是一个QWebElement
  5. 当没有更多元素可用时停止。

这是有效的,因为在调用loadNextChunk()之间,GUI有机会对事件做出反应。

顾名思义,QWebView是一个小部件。另一方面,QWebPage是一个普通的旧QObject,具有您可能想要的所有线程优势。

现在把它绑在一起:

void QWebView::setPage ( QWebPage * page )

相关内容

  • 没有找到相关文章