QtWebkit同步加载

11

我正在使用QWebPage而不是QWebView,因为我想将HTML文件的内容渲染到QPixmap/QImage上。

我想同步加载页面,而不是异步加载(这是默认设置)。默认方式是调用QWebFrame::setHtml()QWebFrame::setContent(),但这会异步加载图片。我需要一种阻塞函数调用的方式,类似于QWebFrame ::waitUntilLoadFinished(),然后我只需调用render()即可完成。

我找不到这样的方法。我错过了什么吗?

4个回答

8
如果有人仍然需要,这就是我的解决方法。
mWebPage->mainFrame()->setHtml("...");
QEventLoop loop;
connect(mWebPage,SIGNAL(loadFinished(bool)),&loop,SLOT(quit()));
loop.exec();
/* your webpage has finished loading & is ready to use */

1
为了更加安全,您可以添加一个带有超时的单次定时器来退出事件循环,以防出现问题:QTimer.singleShot(10000, loop.quit)。 - Pedro Ghilardi

7
我建议您按照Qt的方式进行异步操作,这会帮助很多。

如果您仍然想以同步方式进行操作,请在单独的QThread中使用QEventLoop

有关详细的QThread使用信息,请参见我的评论。 注意:不要忘记在线程头中调用moveToThread();,否则所有信号都将通过QApplication执行循环。


现在看来,这是有用的信息。我不知道QEventLoop。现在我可以将其推到新线程中并等待完成。 - Lucas
2
有关正确使用 QThread,请参见 http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/。 - drahnr

2
那种方法存在的问题是,你基本上必须等待一个不确定的时间,如果你从主线程发出调用,你将阻塞事件处理,因此无法接收象loadFinished这样的信号。虽然你可以通过明确地泵送事件来解决这个问题,但我认为没有什么固有的问题会阻止你在页面加载时发出调用并在loadFinished发生时进行处理。 如果需要二级线程等待页面,则始终可以使用同步机制让这些线程等待。

等待并不是问题,资源来自磁盘且我可以控制它们。它们非常小。但你用 QFutureWatcher 给了我一个想法... - Lucas
此外,我明确希望避免等待信号。我只想从磁盘加载一个小页面,将其呈现为图像并返回该图像。这应该是一个函数,而不是几个函数加上插槽和等待信号等等... - Lucas
由于Qt本身没有提供这个功能,你必须在某个地方等待信号 - 即使它只是被一些代码隐藏起来了。我还没有尝试过Qt的未来观察者,但这个示例看起来可以完全满足你的需求 - 等待信号。 - Georg Fritzsche
但是你需要返回一个QFuture的东西,而QtWebkit中没有任何内容可以做到这一点。 - Lucas
我可能看错了 - 但是你可以使用其他同步机制来为包装器提供支持。 - Georg Fritzsche

0

如果有人感兴趣,我使用了一个特殊的“PageRasterizer”类来实现这个功能。

该类在构造函数中创建一个QWebPage,并将一个bool类型的loading标志设置为false。一个connect()调用将loadFinished信号连接到一个成员槽,该槽仅将loading标志设置为true。

一个特殊的RenderPage()成员函数执行所有工作并返回图像:它接受HTML字符串并调用setHtml()。然后是一个while循环,等待标志;当标志为false时,调用qApp->processEvents()以便信号被发射并最终调用标志设置槽。当它被调用时,循环就会中断,现在你可以将页面渲染为QImage(在返回之前不要忘记将标志重新设置为false)。

如果您对渲染过程感兴趣,请查看this Qt exampleThumbnailer::render()函数)。

为了加分,您可以将这个类变成一个functor。


1
我强烈建议不要使用循环的忙碌轮询,而是采用适当的同步方式,如等待条件。 - Georg Fritzsche
只有在Qt事件循环正在运行时,信号才会被发射。但是事件循环会处理事件然后返回。我的解决方案仅运行Qt事件处理,直到Webkit加载完成。当您无法访问Webkit线程时,我想看到您使用QWaitConditions的代码... - Lucas
我说“推荐”,当然我假设你没有使用主线程作为工作线程,这意味着你不需要手动轮询事件。 - Georg Fritzsche
1
我希望你不是专业程序员,热旋转是你能做的最糟糕的事情。 而且,代码片段通常比解释复杂的结构更有帮助。 你的例子也不需要热旋转。 - drahnr
1
这并不是热旋转,我只是在运行Qt事件循环。 - Lucas
Lucas,你还有这个解决方案的一些示例代码吗?我在使用QtWebkit时遇到了类似的问题。我加载外部网页,直到页面加载完成之前GUI变得很慢。我知道这个答案已经超过2年了,但它看起来很有希望。有什么建议吗? - Cameron Tinker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接