話不多說,先奉上【乾貨代碼】,再奉上【效果圖】,最後有【深度解析】。
【乾貨代碼】如下:
import QtQuick 2.4
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.2
import QtWebEngine 1.2
QtObject {
id: windowParent
property bool isInit: true
// Create the initial browsing windows and open the startup page.
Component.onCompleted: {
var firstWindow = windowComponent.createObject(windowParent)
firstWindow.webView.url = "https://www.baidu.com"
}
property Component windowComponent: Window {
// Destroy on close to release the Window's QML resources.
// Because it was created with a parent, it won't be garbage-collected.
id: wnd
onClosing: destroy();
visible: true
width: 800
height: 600
property var downloads;
property QtObject defaultProfile: WebEngineProfile {
storageName: "Default"
}
property WebEngineView webView: webView_
WebEngineView {
id: webView_
anchors.fill: parent
// Handle the signal. Dynamically create the window and
// use its WebEngineView as the destination of our request.
onNewViewRequested: {
var newWindow = windowComponent.createObject(windowParent)
request.openIn(newWindow.webView)
if (windowParent.isInit) {
profile.downloadRequested.connect(newWindow.onDownloadRequested)
profile.downloadFinished.connect(newWindow.onDownloadFinished)
windowParent.isInit = false;
}
}
}
Rectangle {
id: downloadView
visible: false
width: parent.width - 100
height: 20
color: "green"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
property real progress_val;
Rectangle {
id: progress_complete
color: "red"
anchors.left: parent.left
width: parent.width*downloadView.progress_val
height: parent.height
}
Label {
anchors.left: progress_complete.right
anchors.leftMargin: 10
anchors.verticalCenter: progress_complete.verticalCenter
text:parseInt(downloadView.progress_val*100) + "%"
font.bold: true
color: "red"
}
}
Timer {
id: reloadTimer
interval: 10
running: false
repeat: true
onTriggered: {
downloadView.progress_val = downloads.receivedBytes / downloads.totalBytes
}
}
function onDownloadRequested(download) {
downloadView.visible = true
downloadView.progress_val = download.receivedBytes / download.totalBytes
var arr = download.path.split('/');
var name = arr[arr.length-1];
download.path = "E:/Qt_Test/"+name;
downloads = download;
console.log("download->path=", download.path);
reloadTimer.start();
reloadTimer.running = true;
wnd.width = 300;
wnd.height = 130;
download.accept();
}
function onDownloadFinished(download){
console.log("onDownloadFinished")
reloadTimer.stop();
reloadTimer.running = false;
if (download.state === 2)
{
downloadView.progress_val = 1.0;
}
downloadView.visible = false;
wnd.close();
}
}
}
以上爲核心代碼,接下來奉上運行【效果圖】:【深度解析】:
相比開發簡單瀏覽器,要支持下載,必須要給WebEngineView設置profile屬性,而profile屬性即爲WebEngineProfile,查看Qt幫助,對WebEngineView有如下兩個信號
所以,當給WebEngineView設置了profile屬性後,當WebEngineProfile發送downloadRequested信號時,我們就可以轉入到我們自己的函數中,涉及到信號與槽,就必須對信號槽進行連接,因此,在打開新頁面初次,我們添加了如下代碼:
if (windowParent.isInit) {
profile.downloadRequested.connect(newWindow.onDownloadRequested)
profile.downloadFinished.connect(newWindow.onDownloadFinished)
windowParent.isInit = false;
}
將發送下載請求信號和下載完成信號與對應的槽函數進行連接。至於爲什麼要用windowParent.isInit進行控制,大家都知道,Qt中如果信號和槽連接多次,那麼當信號發出時,就會多次調用連接的槽函數,爲了保證只調一次,這裏做一控制。
這裏需要注意:Qt的幫助有說:
| downloadRequested(WebEngineDownloadItem download)
| This signal is emitted whenever a download has been triggered. The download argument holds |the state of the download. The download has to be explicitly accepted with |WebEngineDownloadItem::accept() or the download will be cancelled by default.
即:在下載請求轉讓我們對應的槽函數onDownloadRequested中後,必須設置download.accept();才表示我們接受下載請求,否則表示我們拒絕下載。
做完以上工作後,我們就可以將網上的圖片和文件下載到本地了(默認下載路徑爲用戶的系統下載目錄)。
接下來介紹一些優化項:
(1)下載的圖片只能下載到用戶的系統下載目錄嗎?不,我們要自己設置自己的下載路徑,因此,這裏就需要對downloadRequested信號所對應的槽函數onDownloadRequested所帶的參數WebEngineDownloadItem進行設置,如下:
var arr = download.path.split('/');var name = arr[arr.length-1];
download.path = "E:/Qt_Test/"+name;
這樣,就將默認的下載路徑改變爲我們自己的"E:/Qt_Test/"目錄下了。
(2)我們想要獲取下載的進度,怎麼辦?對downloadRequested信號所對應的槽函數onDownloadRequested所帶的參數WebEngineDownloadItem進行查看幫助,我們能發現其有兩個屬性 receivedBytes:int 和 totalBytes:int 屬性,通過這兩個屬性,我們就能夠計算出下載進度了^_^。但是問題來了,我們怎樣才能夠實時的去接收這兩個屬性的變化值呢?由於信號只連接一次,因此不能夠讓信號多次連接來更新這兩個屬性值,經過搜索資料以及查看Qt幫助,我們發現,當接收到downloadRequested信號轉入對應槽onDownloadRequested以後,只要我們記住這個槽攜帶的參數,實時讀取這個參數的值,就可以更新進度了(個人猜測這個傳入的參數是引用或指針,Qt在幫助中應該告訴開發者的,否則很難想通的,如果不查看他的demo和幫助,也很少有人想到這裏的),因此設置了一個全局屬性property var downloads;來記住這個值,然後啓用定時器通過downloads對界面進行更新,這樣,就達到了對下載進度的顯示^_^。
至此,QML開發瀏覽並器支持下載功能基本實現了,接下來就是美化和優化界面的事了,這裏就不一一細細道來。