QWebEngineView молча завершается ошибкой при загрузке контента, если выполнение QApplication задерживается - PullRequest
0 голосов
/ 24 января 2019

Мы разрабатываем приложение с пользовательским интерфейсом Qt, содержащим QWebEngineView. В настоящее время тестирую на macOS (10.12..10.14) с Qt 5.9.6

Из-за особенностей ОС приложение иногда ожидает ввода данных пользователем (например, пароль системного администратора), прежде чем набрать QApplication::exec(). Мы поняли, что, если это ожидание занимает слишком много времени, вызовы QWebEngineView::load(QUrl) молча завершаются сбоем, показывая серое представление вместо ожидаемого визуализированного html.

Мы создали минимальный пример, вызывающий проблему в наших тестовых средах:

#include <QApplication>
#include <QMainWindow>
#include <QWebEngineView>
#include <QWidget>

#include <chrono>    
#include <iostream>
#include <thread>

int main(int argc, char *argv[])
{
    QApplication qtapp(argc, argv);

    QMainWindow *window = new QMainWindow;
    window->setFixedSize({800, 600});
    QWebEngineView *webview = new QWebEngineView();
    window->setCentralWidget(webview);

    window->show();

    std::this_thread::sleep_for(std::chrono::seconds(30));
    std::clog << "Done sleeping" << std::endl;

    webview->load({"https://www.google.com"});

    return qtapp.exec();
}

Комментируя sleep, Google home выглядит просто отлично. С sleep мы получаем вместо этого серую область.

  • Есть ли ошибка в использовании Qt в этом примере?
  • Или это ошибка в фреймворке?

Edit: Дальнейшие исследования показывают, что проблема не возникает, пока sleep предшествует как webview->load(), так и window->show().

1 Ответ

0 голосов
/ 24 января 2019

Qt имеет цикл обработки событий, который позволяет вам отслеживать различные события, такие как клавиатура, мышь и т. Д., Поэтому, когда вы используете спящий режим, вы блокируете его и, следовательно, графический интерфейс пользователя зависает, если у вас есть трудоемкие задачи, стратегияэто разделить его на меньшее количество задач. Взвесьте их, если мы сможем или выполним это в новом потоке, и передаем результаты в поток GUI с помощью сигналов.В следующем примере я показываю простую реализацию.

#include <QtWebEngineWidgets>
#include <iostream>

class Worker: public QObject
{
    Q_OBJECT
public:
    using QObject::QObject;
public slots:
    void start_task(){
        std::this_thread::sleep_for(std::chrono::seconds(30));
        std::clog << "Done sleeping" << std::endl;
        emit finished();
    }
signals:
    void finished();
};

class Thread final : public QThread {
    Q_OBJECT
public:
    using QThread::QThread;
    ~Thread() override {
        finish(); wait();
    }
public slots:
    void finish() {
        quit(); requestInterruption();
    }
};

int main(int argc, char *argv[])
{
    QApplication qtapp(argc, argv);
    QMainWindow window;
    window.setFixedSize({800, 600});
    QWebEngineView *webview = new QWebEngineView();
    window.setCentralWidget(webview);
    window.show();
    Thread thread;
    QObject::connect(QApplication::instance(), &QApplication::aboutToQuit, &thread, &Thread::finish);
    thread.start();
    Worker worker;
    worker.moveToThread(&thread);
    QObject::connect(&worker, &Worker::finished, webview, [webview](){
        qDebug()<< "finished";
        webview->load({"https://www.google.com"});
    });
    QMetaObject::invokeMethod(&worker, "start_task", Qt::QueuedConnection);
    return qtapp.exec();
}
#include "main.moc"
...