[英]How to open download file dialog with QWebEngineView?
我正在構建pyqt5桌面界面,在其中使用QWebEngineView來顯示html文件,並在其中顯示Leaflet映射。 一切正常。 下一步是導出用戶添加到地圖的所有要素。 當我單擊地圖上的“導出功能”時,什么也沒有發生,但是當我在Chromium Web瀏覽器中打開相同的html文件時,“導出功能”可以很好地打開下載對話框。
PyQt5腳本:
self.MainWindow.webMapViewer = QtWebEngineWidgets.QWebEngineView()
self.MainWindow.webPageLayout.addWidget(self.MainWindow.webMapViewer)
self.html_path = os.path.split(os.path.abspath(__file__))[0] + r'/html/test.html'
self.MainWindow.webMapViewer.load(QtCore.QUrl().fromLocalFile(self.html_path))
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' />
<title>FazMaraneyRGB_transparent_mosaic_group1</title>
<!-- Leaflet -->
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.js"></script>
<!-- Leaflet.draw -->
<link rel="stylesheet" href="https://unpkg.com/leaflet-draw@0.4.1/dist/leaflet.draw.css" />
<script src="https://unpkg.com/leaflet-draw@0.4.1/dist/leaflet.draw.js"></script>
<!-- Leaflet Ajax -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.min.js"></script>
<!-- Leaflet Measument -->
<link rel="stylesheet" href="http://ljagis.github.io/leaflet-measure/leaflet-measure.css" />
<script src="http://ljagis.github.io/leaflet-measure/leaflet-measure.min.js"></script>
<style>
body { margin:0; padding:0; }
body, table, tr, td, th, div, h1, h2, input { font-family: "Calibri", "Trebuchet MS", "Ubuntu", Serif; font-size: 11pt; }
#map { position:absolute; top:0; bottom:0; width:100%; } /* full size */
.ctl {
padding: 2px 10px 2px 10px;
background: white;
background: rgba(255,255,255,0.9);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
text-align: right;
}
.title {
font-size: 18pt;
font-weight: bold;
}
.src {
font-size: 10pt;
}
#delete, #export {
position: absolute;
top:100px;
right:10px;
z-index:100;
background:white;
color:black;
padding:6px;
border-radius:4px;
font-family: 'Helvetica Neue';
cursor: pointer;
font-size:12px;
text-decoration:none;
}
#export {
top:130px;
}
</style>
</head>
<body>
<div id='map'></div>
<div id='delete'>Delete Features</div>
<a href='#' id='export'>Export Features</a>
<script>
/* **** Leaflet **** */
// Base layers
// .. OpenStreetMap
var osm = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'});
// .. White background
var white = L.tileLayer("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEX///+nxBvIAAAAH0lEQVQYGe3BAQ0AAADCIPunfg43YAAAAAAAAAAA5wIhAAAB9aK9BAAAAABJRU5ErkJggg==");
// Overlay layers (TMS)
var lyr1 = L.tileLayer('./tiles/{z}/{x}/{y}.png', {tms: true, maxZoom: 22, opacity: 0.9, attribution: ""});
// Map
var map = L.map('map', {
measureControl: true,
center: [-18.3604868606589, -52.694255477616245],
zoom: 22,
minZoom: 0,
maxZoom: 22,
layers: [osm]
});
lyr1.addTo(map);
//Geojson Layers
var basemaps = {"OpenStreetMap": osm, "Without background": white}
var overlaymaps = {"Layer 1": lyr1}
// Title
var title = L.control();
title.onAdd = function(map) {
this._div = L.DomUtil.create('div', 'ctl title');
this.update();
return this._div;
};
title.update = function(props) {
this._div.innerHTML = "FazMaraneyRGB_transparent_mosaic_group1";
};
title.addTo(map);
// Note
var src = 'Generated by Hawkit';
var title = L.control({position: 'bottomleft'});
title.onAdd = function(map) {
this._div = L.DomUtil.create('div', 'ctl src');
this.update();
return this._div;
};
title.update = function(props) {
this._div.innerHTML = src;
};
title.addTo(map);
var featureGroup = L.featureGroup().addTo(map);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: featureGroup
}
}).addTo(map);
map.on('draw:created', function(e) {
// Each time a feaute is created, it's added to the over arching feature group
featureGroup.addLayer(e.layer);
});
// on click, clear all layers
document.getElementById('delete').onclick = function(e) {
featureGroup.clearLayers();
}
document.getElementById('export').onclick = function(e) {
// Extract GeoJson from featureGroup
var data = featureGroup.toGeoJSON();
// Stringify the GeoJson
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
// Create export
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download','data.geojson');
}
// Add base layers
L.control.layers(basemaps, overlaymaps, {collapsed: true}).addTo(map);
// Fit to overlay bounds (SW and NE points with (lat, lon))
map.fitBounds([[-18.36827062251916, -52.6871074784942], [-18.35270287637126, -52.7014028427423]]);
</script>
</body>
</html>
該彈出窗口是由瀏覽器生成的,對於QWebEngine
我們必須創建它。 首先,必須檢測到指示下載的信號,然后從QWebEngineProfile
downloadRequested
該信號。 該信號發送給我們一個處理下載的QWebEngineDownloadItem
對象,在其中我們借助QFileDialog
創建一個對話框窗口。 對於這種情況,我們將創建一個自定義QWebEnginePage,如下所示:
的index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' /> <title>FazMaraneyRGB_transparent_mosaic_group1</title> <!-- Leaflet --> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.css" /> <script src="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.js"></script> <!-- Leaflet.draw --> <link rel="stylesheet" href="https://unpkg.com/leaflet-draw@0.4.1/dist/leaflet.draw.css" /> <script src="https://unpkg.com/leaflet-draw@0.4.1/dist/leaflet.draw.js"></script> <!-- Leaflet Ajax --> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.min.js"></script> <!-- Leaflet Measument --> <link rel="stylesheet" href="http://ljagis.github.io/leaflet-measure/leaflet-measure.css" /> <script src="http://ljagis.github.io/leaflet-measure/leaflet-measure.min.js"></script> <style> body { margin: 0; padding: 0; } body, table, tr, td, th, div, h1, h2, input { font-family: "Calibri", "Trebuchet MS", "Ubuntu", Serif; font-size: 11pt; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } /* full size */ .ctl { padding: 2px 10px 2px 10px; background: white; background: rgba(255, 255, 255, 0.9); box-shadow: 0 0 15px rgba(0, 0, 0, 0.2); border-radius: 5px; text-align: right; } .title { font-size: 18pt; font-weight: bold; } .src { font-size: 10pt; } #delete, #export { position: absolute; top: 100px; right: 10px; z-index: 100; background: white; color: black; padding: 6px; border-radius: 4px; font-family: 'Helvetica Neue'; cursor: pointer; font-size: 12px; text-decoration: none; } #export { top: 130px; } </style> </head> <body> <div id='map'></div> <div id='delete'>Delete Features</div> <a href='#' id='export'>Export Features</a> <script> /* **** Leaflet **** */ // Base layers // .. OpenStreetMap var osm = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }); // .. White background var white = L.tileLayer("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEX///+nxBvIAAAAH0lEQVQYGe3BAQ0AAADCIPunfg43YAAAAAAAAAAA5wIhAAAB9aK9BAAAAABJRU5ErkJggg=="); // Overlay layers (TMS) var lyr1 = L.tileLayer('./tiles/{z}/{x}/{y}.png', { tms: true, maxZoom: 22, opacity: 0.9, attribution: "" }); // Map var map = L.map('map', { measureControl: true, center: [-18.3604868606589, -52.694255477616245], zoom: 22, minZoom: 0, maxZoom: 22, layers: [osm] }); lyr1.addTo(map); //Geojson Layers var basemaps = { "OpenStreetMap": osm, "Without background": white } var overlaymaps = { "Layer 1": lyr1 } // Title var title = L.control(); title.onAdd = function(map) { this._div = L.DomUtil.create('div', 'ctl title'); this.update(); return this._div; }; title.update = function(props) { this._div.innerHTML = "FazMaraneyRGB_transparent_mosaic_group1"; }; title.addTo(map); // Note var src = 'Generated by Hawkit'; var title = L.control({ position: 'bottomleft' }); title.onAdd = function(map) { this._div = L.DomUtil.create('div', 'ctl src'); this.update(); return this._div; }; title.update = function(props) { this._div.innerHTML = src; }; title.addTo(map); var featureGroup = L.featureGroup().addTo(map); var drawControl = new L.Control.Draw({ edit: { featureGroup: featureGroup } }).addTo(map); map.on('draw:created', function(e) { // Each time a feaute is created, it's added to the over arching feature group featureGroup.addLayer(e.layer); }); // on click, clear all layers document.getElementById('delete').onclick = function(e) { featureGroup.clearLayers(); } document.getElementById('export').onclick = function(e) { // Extract GeoJson from featureGroup var data = featureGroup.toGeoJSON(); // Stringify the GeoJson var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data)); // Create export document.getElementById('export').setAttribute('href', 'data:' + convertedData); document.getElementById('export').setAttribute('download', 'data.geojson'); } // Add base layers L.control.layers(basemaps, overlaymaps, { collapsed: true }).addTo(map); // Fit to overlay bounds (SW and NE points with (lat, lon)) map.fitBounds([ [-18.36827062251916, -52.6871074784942], [-18.35270287637126, -52.7014028427423] ]); </script> </body> </html>
main.py
from PyQt5 import QtWebEngineWidgets, QtWidgets, QtCore
class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
def __init__(self, *args, **kwargs):
QtWebEngineWidgets.QWebEnginePage.__init__(self, *args, **kwargs)
self.profile().downloadRequested.connect(self.on_downloadRequested)
@QtCore.pyqtSlot(QtWebEngineWidgets.QWebEngineDownloadItem)
def on_downloadRequested(self, download):
old_path = download.path()
suffix = QtCore.QFileInfo(old_path).suffix()
path, _ = QtWidgets.QFileDialog.getSaveFileName(self.view(), "Save File", old_path, "*."+suffix)
if path:
download.setPath(path)
download.accept()
if __name__ == '__main__':
import sys
sys.argv.append("--remote-debugging-port=8000")
sys.argv.append("--disable-web-security")
app = QtWidgets.QApplication(sys.argv)
view = QtWebEngineWidgets.QWebEngineView()
page = WebEnginePage(view)
view.setPage(page)
path = QtCore.QDir.current().filePath("index.html")
view.load(QtCore.QUrl.fromLocalFile(path))
view.show()
sys.exit(app.exec_())
在您的情況下:
self.MainWindow.webMapViewer = QtWebEngineWidgets.QWebEngineView()
self.MainWindow.webPageLayout.addWidget(self.MainWindow.webMapViewer)
page = WebEnginePage(self.MainWindow.webMapViewer) # create page
self.MainWindow.webMapViewer.setPage(page) # set page
self.html_path = os.path.split(os.path.abspath(__file__))[0] + r'/html/test.html'
self.MainWindow.webMapViewer.load(QtCore.QUrl().fromLocalFile(self.html_path))
加:
如果要設置定義的路由,請使用以下命令:
@QtCore.pyqtSlot(QtWebEngineWidgets.QWebEngineDownloadItem)
def on_downloadRequested(self, download):
directory = "/path/of/directory"
filename = QtCore.QFileInfo(download.path()).fileName()
download.setPath(QtCore.QDir(directory).filePath(filename))
download.accept()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.