Qt WebEngine Widgets的使用

一、Qt WebEngine基本概念

Qt WebEngine中主要分为三个模块:Qt WebEngine Widgets模块,主要用于创建基于C++ Widgets部件的Web程序;Qt WebEngine模块用来创建基于Qt Quick的Web程序;Qt WebEngine Core模块用来与Chromeium交互。网页玄幻和JavaScript的执行从GUI进程分离到Qt WebEngine进程,主要架构如下。

二、Qt WebEngine Widgets

本文主要关注Qt WebEngine Widgets模块,其架构如下。QWebEngineView是主要窗体类组件,用来加载Web。QWebEnginePage包含在QWebEngineView中,主要包含了Web页面的主框架,负责内容分、浏览历史QWebEngineHistory等。配置QWebEngineProfile用于区分不同的Page,属于同一个Web引擎配置的所有网页共享设置Settings、脚本Script和Cookies。

三、一个简易的浏览器

重写QWebenginePage的acceptNavigationRequest进行导航设置,没有特殊需求可只用用基类。

cpp 复制代码
class CustomWebEnginePage : public QWebEnginePage {
	Q_OBJECT
public:
	CustomWebEnginePage(QObject *parent = nullptr) : QWebEnginePage(parent) {}

	bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) override {
		if (type == QWebEnginePage::NavigationTypeLinkClicked && isMainFrame) {
			load(url); // 允许在当前页面打开新链接
			return false; // 阻止默认打开新窗口的行为
		}
		return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame);
	}
};

浏览器页面实现细节:

cpp 复制代码
void Test2015::TestWebEngineWidget()
{
	if (ui.frameWeb)
	{
		auto& pParent = ui.webEngineView;
		auto& pWebView = ui.webEngineView;
		//pWebView->setPage(new CustomWebEnginePage(pWebView));
		pWebView->load(QUrl("https://blog.csdn.net/WSTONECH?type=blog"));
		QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);

		pWebView->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
		pWebView->settings()->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain, true);

		//工具栏
		urlEdit = new QLineEdit(pParent);
		backButton = new QPushButton("Back", pParent);
		forwardButton = new QPushButton("Forward", pParent);
		refreshButton = new QPushButton("Refresh", pParent);
		goButton = new QPushButton("Go", pParent);
		favBtn = new QPushButton("收藏", pParent);


		QHBoxLayout *toolbarLayout = new QHBoxLayout(ui.frameToolBar);
		toolbarLayout->addWidget(backButton);
		toolbarLayout->addWidget(forwardButton);
		toolbarLayout->addWidget(refreshButton);
		toolbarLayout->addWidget(urlEdit);
		toolbarLayout->addWidget(goButton);
		toolbarLayout->addWidget(favBtn);


		//历史记录ListView
		historyModel = new QStringListModel(pParent);
		ui.listView_History->setModel(historyModel);

		//进度条
		ui.progressBar->setMaximum(100);
		ui.progressBar->setVisible(false);

		//
		connect(urlEdit, &QLineEdit::returnPressed, [=]() {
			QString urlStr = urlEdit->text().trimmed();
			QUrl url = urlStr.startsWith("http") ? QUrl(urlStr) : QUrl("https://" + urlStr);
			if (url.isValid()) {
				pWebView->setUrl(url);
			}
		});
		connect(pWebView->page(), &QWebEnginePage::urlChanged, urlEdit, [=](QUrl url) {
			urlEdit->setText(url.toString());
		});

		//进度条更新
		connect(pWebView, &QWebEngineView::loadProgress, this, [=](int progressValue) {
			if (progressValue == 100) {
				ui.progressBar->setVisible(false);
		}
		else {
			ui.progressBar->setVisible(true);
			ui.progressBar->setValue(progressValue);
		}});

		//更新历史地址 页面加载完成在记录历史地址防止未完全加载title等无法解析
		connect(pWebView, &QWebEngineView::loadFinished, this, [=](bool ok) {
			if (ok)
			{
				historyUrls.clear();
				QList<QWebEngineHistoryItem> items = pWebView->history()->items();
				for (const QWebEngineHistoryItem& item : items) {
					if (item.isValid() && (item.url().toString() != "about:blank"))
					{
						string title = item.title().toStdString();
						string urlstr = item.url().toString().toStdString();
						historyUrls.append(item.title() + " - " + item.url().toString());
					}
				}
				historyModel->setStringList(historyUrls);
			}
		});

		//
		connect(ui.listView_History->selectionModel(), &QItemSelectionModel::currentChanged,
			this, [=](const QModelIndex& index) {
				if (!index.isValid()) return;

				QList<QWebEngineHistoryItem> items = pWebView->history()->items();
				if (index.row() >= 0 && index.row() < items.size()) {
					pWebView->load(items[index.row()].url());
				}
		});

		connect(favBtn, &QPushButton::clicked, this, [=]() {
			QString url = pWebView->url().toString();
		});
	
	

		connect(backButton, &QPushButton::clicked, this, [=]() {
			if (pWebView->page()->history()->canGoBack()) {
				pWebView->back();
			}
		});
		connect(forwardButton, &QPushButton::clicked, this, [=]() {
			if (pWebView->page()->history()->canGoForward()) {
				pWebView->forward();
			}
		});
		connect(refreshButton, &QPushButton::clicked, pWebView, &QWebEngineView::reload);
		connect(goButton, &QPushButton::clicked, this, [=]() {
			QString input = urlEdit->text();
			QUrl url;
			if (input.startsWith("http://") || input.startsWith("https://")) {
				url = QUrl(input);
			}
			else {
				url = QUrl("https://" + input);
			}
			if (url.isValid()) {
				pWebView->setUrl(url);
			}
		});
	}
}

实现效果​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

相关推荐
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
C语言小火车4 天前
C/C++ 为什么需要编译器?
开发语言·c++
霍霍的袁4 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
孙启超4 天前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int4 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++
慧都小项4 天前
当边缘AI上产线:QtitanDocking 如何让工业 HMI 实现多视图协同
人工智能·qt·ui·边缘计算·qt6.3
CoderYanger4 天前
A.每日一题:835. 图像重叠
java·开发语言·程序人生·leetcode·面试·职场和发展·学习方法
伞伞悦读4 天前
【第37期】Python JSON 与配置详解:序列化、反序列化、嵌套结构和配置文件
开发语言·python·json
CCCCCCCCharlie4 天前
Linux进程控制四大核心操作
linux·开发语言