QWebView setContent в отдельном потоке

У меня есть приложение, которое требует использования QWebView::setContent() загрузить некоторый контент HTML в QWebView. Все это происходит на встроенном устройстве с процессором ARMv5 (думаю, 400 МГц). Большую часть времени я могу загрузить страницу за разумное время (до 5 секунд), однако иногда у меня есть контент, который загружается долго (~30 секунд для 300 КБ контента).

Проблема в том, что setContent вызов блокирует основной поток. Мне нужно иметь возможность обрабатывать события во время загрузки и, возможно, даже отменить загрузку, если пользователь решает больше не ждать.

Я думал о запуске setContent позвоните в другой поток, чтобы он не блокировал обработку события, и я могу отменить его при необходимости. Тем не менее, я получаю страшные "виджеты должны быть созданы в потоке GUI", и я не вижу способа решить это легко.

Можно ли бежать QWebView::setContent в отдельной теме? Если так, то как? Если нет, то возможно ли обрабатывать события GUI, пока setContent бежит? Можно ли "отменить" setContent вызов?

РЕДАКТИРОВАТЬ

Чтобы прояснить немного больше, меня действительно интересует, как можно остановить setContent вызывать и / или обрабатывать сообщения с графическим интерфейсом, чтобы интерфейс оставался отзывчивым, передавая большие объемы данных с использованием setContent,

РЕДАКТИРОВАТЬ 2

Чтобы пояснить еще больше, я имею дело с длинным статическим контентом, то есть без JavaScript, просто с большим количеством статического HTML, который пользователь хочет прокручивать, даже когда он загружает больше контента. Основная идея заключается в том, чтобы позволить ему / ей перейти на страницу, даже если страница загружена не полностью.

3 ответа

Решение

Поскольку QWebView::setContent() это блокирующий вызов, я в конечном итоге использовать обходной путь. Основная идея заключается в том, что обработка XML намного быстрее, чем рендеринг страницы. Поэтому я делаю следующее:

  1. Разобрать документ как документ XML DOM (разумное предположение в моем случае) и найти body элемент.
  2. Оставьте только заранее определенное количество дочерних элементов body (что-то вроде 20 элементов). Сохраните остальные элементы в другом документе XML DOM.
  3. Показать исходный документ (сериализованный XML), используя QWebView::setContent(), что относительно быстро. Запустить таймер с таймаутом 0 на SLOT(loadNextChunk()),
  4. loadNextChunk() перемещает еще 20 или около того элементов из резервного документа в конце тела, используя body->appendInside(html), где body это QWebElement,
  5. Остановитесь, когда больше нет доступных элементов.

Это работает, потому что между вызовами loadNextChunk()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, как следует из его названия, является виджетом. QWebPage, с другой стороны, является простым старым QObject, со всеми качествами потоков, которые вы, возможно, захотите.

Теперь свяжите это вместе:

void QWebView::setPage ( QWebPage * page )
Другие вопросы по тегам