c++ - 如果 QApplication 执行延迟,QWebEngineView 在加载内容时会静默失败
问题描述
我们正在开发一个带有 Qt UI 的应用程序,其中包含QWebEngineView
. 目前正在使用 Qt 5.9.6 在 macOS (10.12..10.14) 上进行测试
由于操作系统的特殊性,应用程序有时会等待用户输入(例如系统管理员密码),然后才能到达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
谷歌主页就可以了。有了sleep
,我们得到了灰色区域。
- 在这个例子中使用 Qt 是否有错误?
- 或者这是框架中的错误?
编辑:进一步调查表明,只要在和sleep
之前,问题就不会发生。webview->load()
window->show()
解决方案
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"
推荐阅读
- r - 如何在R中的多行字符串中查找字符串第一行的长度
- c# - 网站浏览表单指定设备
- swift - 使用 AppKit 实现高更新率 GUI 的有效方法是什么?
- vue.js - 无法读取 Vuex/Nuxt 中未定义的属性“名称”
- c# - 使用多个连接、SUM 和 group by 将 SQL 转换为 Linq
- image - 如何将图像从 url 显示到 Qlabel
- vue.js - Nginx 重定向与 vue 不工作 - 404
- java - 找不到符号:类 OneofDescriptor
- java - 杰克逊:SerializationConfig.hasExplicitTimeZone()
- javascript - jQuery删除文件后删除DropZone.js缩略图