Синхронная загрузка QtWebkit
Я использую QWebPage без QWebView, потому что хочу отображать содержимое HTML файла в QPixmap/QImage.
Я хочу, чтобы загрузка страницы выполнялась синхронно, а не асинхронно, что по умолчанию. По умолчанию используется вызов QWebFrame::setHtml()
или QWebFrame::setContent()
, но он загружает изображения асинхронно. Я хочу, это какой-то вызов функции блокировки, что-то вроде QWebFrame::waitUntilLoadFinished()
, после чего я мог просто вызвать render()
и сделать с ним.
Я не могу найти способ сделать это. Я что-то пропустил?
Ответы
Ответ 1
Если кто-то заинтересован, я применил это, используя специальный класс "PageRasterizer".
Класс создает QWebPage в конструкторе и устанавливает флаг загрузки bool в значение false. A connect()
соединяет сигнал loadFinished
с слотом участника, который просто устанавливает флаг загрузки в значение true.
Специальная функция-член RenderPage()
, которая возвращает изображение, выполняет всю работу: он принимает строку HTML и вызывает setHtml()
. После этого появляется цикл while
, который ждет флаг; в то время как флаг является ложным, qApp->processEvents()
вызывается так, что сигналы выдаются, и слот установки флага в конечном итоге вызывается. Когда это произойдет, цикл прерывается, и теперь вы можете отобразить страницу в QImage (не забудьте вернуть флаг к false до возвращения).
Если вы заинтересованы в процессе рендеринга, посмотрите этот пример Qt (функция Thumbnailer::render()
).
Для бонусных очков вы можете сделать этот класс функтором.
Ответ 2
Я предлагаю вам сделать это способом Qt и сделать это асинхронно, это очень помогает.
Если вы все еще хотите сделать это в Sync, используйте QEventLoop в отдельном QThread.
См. мой комментарий для подробной информации об использовании QThread.
Примечание: не забудьте вызвать moveToThread(); в заголовке потока, или все сигналы будут проходить через цикл выполнения QApplication.
Ответ 3
Если кто-то все еще нуждается в этом, вот как я его работаю.
mWebPage->mainFrame()->setHtml("...");
QEventLoop loop;
connect(mWebPage,SIGNAL(loadFinished(bool)),&loop,SLOT(quit()));
loop.exec();
/* your webpage has finished loading & is ready to use */
Ответ 4
У этого подхода есть проблема, что вам в основном приходится ждать неопределенного количества времени, и если вы выходите из основного потока, вы блокируете обработку событий и, таким образом, сигнализируете, как loadFinished
.
Пока вы можете обойти это с помощью явного события накачки, я не вижу врожденной проблемы, которая может помешать вам загрузить загрузку страницы и просто выполнить обработку, когда произошел loadFinished
.
Если вам нужны дополнительные потоки для ожидания страницы, вы всегда можете позволить этим потокам ждать с помощью механизмов синхронизации.