我有一个应用程序需要使用QWebView::setContent()
将一些HTML内容加载到QWebView。所有这些都发生在具有ARMv5处理器的嵌入式设备上(想想400 MHz)。大多数情况下,我可以在合理的时间内(最多5秒)加载页面,但有时我的内容需要很长时间才能加载(300KB内容约30秒)。
问题是setContent
调用阻塞了主线程。我需要能够在加载过程中处理事件,如果用户决定不再等待,甚至可以取消加载。
我正考虑在其他线程中运行setContent
调用,这样它就不会阻止事件处理,我可以在必要时取消它。但是,我得到了可怕的"widgets must be created in the GUI thread",我认为没办法轻易解决这个问题。
是否可以在单独的线程中运行QWebView::setContent
?如果是这样,怎么样?如果没有,是否可以在setContent
运行时处理GUI事件?是否可以“取消”setContent
来电?
修改
为了澄清一点,我真正感兴趣的是如何能够停止setContent
调用和/或处理GUI消息,以便界面保持响应,使用{{传递大量数据1}}。
编辑2
为了进一步澄清,我正在处理长静态内容,即没有JavaScript,只有很多静态HTML,即使在加载更多内容时用户也希望滚动它。主要想法是即使页面没有满载也允许她/他下页。
答案 0 :(得分:2)
前段时间我遇到了类似的问题。据我所知,只有页面的主要内容是同步的。
事实是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)只要您需要取消加载,您就可以加载其他内容,删除内容文件或其他可能的方法。
请注意,据我所知,你永远不会异步内容的绘画。这是嵌入式系统中的真正问题。
答案 1 :(得分:1)
由于QWebView::setContent()
是阻止通话,我最终使用了解决方案。主要思想是XML处理比呈现页面快得多。因此,我会做以下事情:
body
元素。body
子元素(类似于20个元素)。将其余元素存储在另一个XML DOM文档中。QWebView::setContent()
显示初始文档(序列化XML),这相对较快。在SLOT(loadNextChunk())
上启动超时为0的计时器。loadNextChunk()
使用body->appendInside(html)
从正文末尾的备份文档移动另外20个元素,其中body
为QWebElement
。这是有效的,因为在调用loadNextChunk()
之间,GUI有机会对事件做出反应。
答案 2 :(得分:0)
顾名思义,QWebView是一个小部件。另一方面,QWebPage是一个普通的旧QObject,具有您可能想要的所有线程优点。
现在把它绑在一起:
void QWebView::setPage ( QWebPage * page )