2010-02-05 84 views
10

我正在使用没有QWebView的QWebPage,因为我想将HTML文件的内容渲染到QPixmap/QImage上。QtWebkit同步加载

我想要加载的页面是同步完成的,不是这是默认的异步。默认的方法是调用QWebFrame::setHtml()QWebFrame::setContent(),但这会异步加载图像。我想要的是某种阻塞函数调用,如QWebFrame::waitUntilLoadFinished()之后,我可以拨打render()并完成它。

我找不到办法做到这一点。我错过了什么吗?

回答

0

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

该类在构造函数中创建一个QWebPage,并将bool加载标志设置为false。 A connect()呼叫将loadFinished信号连接到仅将加载标志设置为真的成员插槽。

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

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

对于奖励积分,您可以将此课程作为函数。

+1

我绝对建议不要通过循环使用繁忙的轮询,而是像等待条件一样进行适当的同步。 – 2010-02-06 14:26:44

+0

除非Qt事件循环正在运行,否则信号不会被发射。但事件循环处理事件然后返回。我的解决方案只是运行Qt事件处理,直到Webkit完成加载。 我想看看你的代码使用QWaitConditions _when你没有访问Webkit线程_... – Lucas 2010-02-06 15:01:51

+0

我说*推荐*,当然我假设你没有使用主线程作为工作线程,这意味着你根本不需要手动轮询事件。 – 2010-02-07 21:05:18

2

该方法存在的问题是,您基本上需要等待不确定的时间,并且如果您从主线程发出呼叫,则会阻止事件处理,因此信号如loadFinished

虽然你可以得到解决,通过显式泵送事件,我不认为这会阻止您发布页面加载一个固有的问题,只是做加工时loadFinished发生。
如果您需要辅助线程来等待页面,则可以始终让这些线程使用同步机制进行等待。

+0

等待不是问题,资源来自磁盘,我控制它们。他们非常小。但是你给了我一个关于QFutureWatcher的想法...... – Lucas 2010-02-05 15:23:02

+0

另外,我明确地希望避免等待信号。我只想从磁盘加载一个小页面,将其渲染为图像并返回该图像。这应该是一个功能,而不是几个+插槽+等待信号等等。 – Lucas 2010-02-05 15:25:55

+0

由于Qt本身没有提供,所以你必须等待信号 - 即使它只是被某些代码隐藏。我还没有试过Qts未来的观察者,但是这个例子看起来像它可以做到你想要的 - 等待信号。 – 2010-02-05 15:48:48

7

我建议你这样做的Qt方式,并做到异步,它帮助很多

如果您仍想在同步中执行此操作,请在单独的QThread中使用QEventLoop

查看我的评论,了解详细的QThread使用信息。注意:不要忘记调用moveToThread();在线程头文件中,或者所有的信号将通过QApplication执行循环。

+0

现在看_that's_有用的信息。我不知道QEventLoop。现在我可以将它推到一个新线程并等待完成。 – Lucas 2010-02-08 23:38:30

+0

相当悲伤我仍然得到了“解决”,也没有upvote:P – drahnr 2010-02-09 08:16:13

+2

正确的QThread用法见http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ – drahnr 2011-05-22 19:24:07

7

如果有人仍然需要它,这是我如何得到它的工作。

mWebPage->mainFrame()->setHtml("..."); 
QEventLoop loop; 
connect(mWebPage,SIGNAL(loadFinished(bool)),&loop,SLOT(quit())); 
loop.exec(); 
/* your webpage has finished loading & is ready to use */ 
+0

OMG。这样可行!非常感谢。 – 2014-12-31 16:00:42

+1

为了更加安全,您可以添加一个带有超时的单次计时器,以在出现错误时退出事件循环:QTimer.singleShot(10000,loop.quit) – 2016-05-23 18:17:02