QML WebEngineView 电影内容
QML WebEngineView flick content
我正在尝试使用 QML 和 WebEngineView 组件使用 Ubuntu 14.04 为桌面制作一个简单的网络浏览器。该应用程序将在带有触摸板的设备上运行,因此最好使显示在 WebEngineView 中的内容可轻弹。
我试过这样做,但是不行:
...
WebEngineView {
id: webView
url: "http://google.com"
width: parent.width
height: winternet.height-navigationBar.height-iStatusBar.height-iBackButton.height
anchors.top: navigationBar.bottom
MouseArea {
anchors.fill: parent
drag.target: parent.data
}
onLinkHovered: {
webView.url = hoveredUrl
}
}
...
如果您对此有任何想法或经验,请提供帮助!
我想WebEngineView flickable too. I decided, that it's better to do it using Flickable。但是天真的做法是:
...
Flickable {
WebEngineView {...}
}
...
不会工作。
进一步的调查让我找到 Qt based Web browser for embedded touch devices。我已经在我的电脑上试过了。看起来它正在做我想要的,但它太复杂了,而且 GPL 许可使它无法用于任何类型的用途。
经过一些实验后,我发现如果 Flickable.contentHeight and Flickable.contentWidth 至少与 WebEngineView 显示的网页的实际大小相匹配,轻弹就会起作用。 Flickable 的这些属性可能具有比实际页面大小更大的值。在这种情况下,您将能够超越页面内容。如果 Flickable.contentHeight and/or Flickable.contentWidth 小于页面大小,您仍然可以轻弹。这取决于你是否想要这样)
因此最终获取显示的实际页面大小并将其设置为 Flickable.contentHeight 和 Flickable.contentWidth。我将在这里给您讲一个小故事:无法使用 WebEngineView API 获得所需的值(或者至少我在 Qt 5.7/5.8 文档中没有找到任何内容)。但是我无意中发现了this answer on SO。使用这个答案,我设法使一切正常:
...
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Flickable {
id: flick
anchors.fill: parent
WebEngineView {
anchors.fill: parent
id: webView
}
}
webView.onLoadingChanged: {
if (webView.loadProgress == 100) {
webView.runJavaScript(
"document.documentElement.scrollHeight;",
function (i_actualPageHeight) {
flick.contentHeight = Math.max (
i_actualPageHeight, flick.height);
})
webView.runJavaScript(
"document.documentElement.scrollWidth;",
function (i_actualPageWidth) {
flick.contentWidth = Math.max (
i_actualPageWidth, flick.width);
})
}
}
}
...
上面截取的代码可能需要进行一些调整,但它几乎是我所用代码的副本。
UPD 1:我发现这不是最终解决方案,因为出于某种原因,在加载新页面后 document.documentElement.scrollWidth 可能无法重置并保持与前一页相同。
UPD 2:我已经解决了上述问题,但解决方案有点难看:将WebEngineView.onLoadingChanged中的Flickable.contentWidth重置为Flickable.width。将 Flickable.contentWidth 设置为 0 将导致加载后内容的高度过大。
我所做的另一项调整是取消了对 100% 加载状态的要求。
UPD 3:可轻弹的 WebEngiveView 的更完整版本。使用用户脚本而不是直接调用 JavaScript 因为我在使用后者时遇到了一些导致 WebEngineView 关闭的奇怪错误。
// Copyright 2019 Utility Tool Kit Open Source Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// Author: Innokentiy Alaytsev <alaitsev@gmail.com>
//
// File name: qml/Utk/Qml/FlickableWebEngineView.qml
//
// Description: The QML FlickableWebEngineView QtQuick 2 component.
import QtQuick 2.7
import QtWebEngine 1.3
Item {
property alias flickable: flickable;
property alias webView: webView;
property bool userDragImgEnabled: true;
property bool userSelectEnabled: true;
readonly property string kDisableUserDragCssId:
"utk_qml_flickable_web_engine_view_disable_user_drag_css";
readonly property string kDisableUserSelectCssId:
"utk_qml_flickable_web_engine_view_disable_user_select_css";
readonly property string kDisableUserDragCss:
"{ \ \
-webkit-user-drag: none; \ \
-khtml-user-drag: none; \ \
-moz-user-drag: none; \ \
-ms-user-drag: none; \ \
user-drag: none; \ \
}";
readonly property string kDisableUserSelectCss:
"{ \ \
-webkit-touch-callout: none; \ \
-webkit-user-select: none; \ \
-khtml-user-select: none; \ \
-moz-user-select: none; \ \
-ms-user-select: none; \ \
user-select: none; \ \
}";
WebEngineScript {
id: disableUserDragScript;
name: kDisableUserDragCssId;
injectionPoint: WebEngineScript.DocumentReady;
sourceCode: applyCssJavaScript ("img", kDisableUserDragCss, kDisableUserDragCssId);
worldId: WebEngineScript.MainWorld;
}
WebEngineScript {
id: disableUserSelectScript;
name: kDisableUserSelectCssId;
injectionPoint: WebEngineScript.DocumentReady;
sourceCode: applyCssJavaScript ("body", kDisableUserSelectCss, kDisableUserSelectCssId);
worldId: WebEngineScript.MainWorld;
}
Flickable {
id: flickable;
anchors.fill : parent;
clip: true;
WebEngineView {
id: webView;
anchors.fill : parent;
scale: 1;
onLoadingChanged: {
if (loadRequest.status !== WebEngineView.LoadSucceededStatus) {
return;
}
flickable.contentHeight = 0;
flickable.contentWidth = flickable.width;
runJavaScript (
"document.documentElement.scrollHeight;",
function (actualPageHeight) {
flickable.contentHeight = Math.max (
actualPageHeight, flickable.height);
});
runJavaScript (
"document.documentElement.scrollWidth;",
function (actualPageWidth) {
flickable.contentWidth = Math.max (
actualPageWidth, flickable.width);
});
}
}
}
onUserDragImgEnabledChanged: {
if (userDragImgEnabled &&
(webView.loadRequest.status === WebEngineView.LoadSucceededStatus)) {
runJavaScript (revertCssJavaScript (kDisableUserDragCssId));
}
else {
webView.userScripts = currentUserScripts ();
}
}
onUserSelectEnabledChanged: {
if (userSelectEnabled &&
(webView.loadRequest.status === WebEngineView.LoadSucceededStatus)) {
runJavaScript (revertCssJavaScript (kDisableUserSelectCssId));
}
else {
webView.userScripts = currentUserScripts ();
}
}
function currentUserScripts () {
var userScriptsToSkip = [
disableUserDragScript.name,
disableUserSelectScript.name
];
var updatedUserScripts = [];
for (var i in webView.userScripts) {
var script = webView.userScripts[ i ];
if (-1 == userScriptsToSkip.indexOf (script.name)) {
updatedUserScripts.push (script);
}
}
if (!userDragImgEnabled) {
updatedUserScripts.push (disableUserDragScript);
}
if (!userSelectEnabled) {
updatedUserScripts.push (disableUserSelectScript);
}
return updatedUserScripts;
}
function applyCssJavaScript (selector, css, cssId) {
var applyCssJavaScript =
"(function () { \
cssElement = document.createElement ('style'); \
\
head = document.head || \
document.getElementsByTagName ('head')[ 0 ]; \
\
head.appendChild (cssElement); \
\
cssElement.type = 'text/css'; \
cssElement.id = '%1'; \
\
if (cssElement.styleSheet) \
{ \
cssElement.styleSheet.cssText = '%2 %3'; \
} \
else \
{ \
cssElement.appendChild ( \
document.createTextNode ('%2 %3')); \
} \
})();";
return applyCssJavaScript
.arg (cssId)
.arg (selector)
.arg (css);
}
function revertCssJavaScript (cssId) {
var revertCssJavaScript =
"(function () { \
var element = document.getElementById('%1'); \
\
if (element) { \
element.outerHTML = ''; \
\
delete element; \
} \
})()";
return revertCssJavaScript.arg (cssId);
}
}
我正在尝试使用 QML 和 WebEngineView 组件使用 Ubuntu 14.04 为桌面制作一个简单的网络浏览器。该应用程序将在带有触摸板的设备上运行,因此最好使显示在 WebEngineView 中的内容可轻弹。
我试过这样做,但是不行:
...
WebEngineView {
id: webView
url: "http://google.com"
width: parent.width
height: winternet.height-navigationBar.height-iStatusBar.height-iBackButton.height
anchors.top: navigationBar.bottom
MouseArea {
anchors.fill: parent
drag.target: parent.data
}
onLinkHovered: {
webView.url = hoveredUrl
}
}
...
如果您对此有任何想法或经验,请提供帮助!
我想WebEngineView flickable too. I decided, that it's better to do it using Flickable。但是天真的做法是:
...
Flickable {
WebEngineView {...}
}
...
不会工作。
进一步的调查让我找到 Qt based Web browser for embedded touch devices。我已经在我的电脑上试过了。看起来它正在做我想要的,但它太复杂了,而且 GPL 许可使它无法用于任何类型的用途。
经过一些实验后,我发现如果 Flickable.contentHeight and Flickable.contentWidth 至少与 WebEngineView 显示的网页的实际大小相匹配,轻弹就会起作用。 Flickable 的这些属性可能具有比实际页面大小更大的值。在这种情况下,您将能够超越页面内容。如果 Flickable.contentHeight and/or Flickable.contentWidth 小于页面大小,您仍然可以轻弹。这取决于你是否想要这样)
因此最终获取显示的实际页面大小并将其设置为 Flickable.contentHeight 和 Flickable.contentWidth。我将在这里给您讲一个小故事:无法使用 WebEngineView API 获得所需的值(或者至少我在 Qt 5.7/5.8 文档中没有找到任何内容)。但是我无意中发现了this answer on SO。使用这个答案,我设法使一切正常:
...
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Flickable {
id: flick
anchors.fill: parent
WebEngineView {
anchors.fill: parent
id: webView
}
}
webView.onLoadingChanged: {
if (webView.loadProgress == 100) {
webView.runJavaScript(
"document.documentElement.scrollHeight;",
function (i_actualPageHeight) {
flick.contentHeight = Math.max (
i_actualPageHeight, flick.height);
})
webView.runJavaScript(
"document.documentElement.scrollWidth;",
function (i_actualPageWidth) {
flick.contentWidth = Math.max (
i_actualPageWidth, flick.width);
})
}
}
}
...
上面截取的代码可能需要进行一些调整,但它几乎是我所用代码的副本。
UPD 1:我发现这不是最终解决方案,因为出于某种原因,在加载新页面后 document.documentElement.scrollWidth 可能无法重置并保持与前一页相同。
UPD 2:我已经解决了上述问题,但解决方案有点难看:将WebEngineView.onLoadingChanged中的Flickable.contentWidth重置为Flickable.width。将 Flickable.contentWidth 设置为 0 将导致加载后内容的高度过大。
我所做的另一项调整是取消了对 100% 加载状态的要求。
UPD 3:可轻弹的 WebEngiveView 的更完整版本。使用用户脚本而不是直接调用 JavaScript 因为我在使用后者时遇到了一些导致 WebEngineView 关闭的奇怪错误。
// Copyright 2019 Utility Tool Kit Open Source Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// Author: Innokentiy Alaytsev <alaitsev@gmail.com>
//
// File name: qml/Utk/Qml/FlickableWebEngineView.qml
//
// Description: The QML FlickableWebEngineView QtQuick 2 component.
import QtQuick 2.7
import QtWebEngine 1.3
Item {
property alias flickable: flickable;
property alias webView: webView;
property bool userDragImgEnabled: true;
property bool userSelectEnabled: true;
readonly property string kDisableUserDragCssId:
"utk_qml_flickable_web_engine_view_disable_user_drag_css";
readonly property string kDisableUserSelectCssId:
"utk_qml_flickable_web_engine_view_disable_user_select_css";
readonly property string kDisableUserDragCss:
"{ \ \
-webkit-user-drag: none; \ \
-khtml-user-drag: none; \ \
-moz-user-drag: none; \ \
-ms-user-drag: none; \ \
user-drag: none; \ \
}";
readonly property string kDisableUserSelectCss:
"{ \ \
-webkit-touch-callout: none; \ \
-webkit-user-select: none; \ \
-khtml-user-select: none; \ \
-moz-user-select: none; \ \
-ms-user-select: none; \ \
user-select: none; \ \
}";
WebEngineScript {
id: disableUserDragScript;
name: kDisableUserDragCssId;
injectionPoint: WebEngineScript.DocumentReady;
sourceCode: applyCssJavaScript ("img", kDisableUserDragCss, kDisableUserDragCssId);
worldId: WebEngineScript.MainWorld;
}
WebEngineScript {
id: disableUserSelectScript;
name: kDisableUserSelectCssId;
injectionPoint: WebEngineScript.DocumentReady;
sourceCode: applyCssJavaScript ("body", kDisableUserSelectCss, kDisableUserSelectCssId);
worldId: WebEngineScript.MainWorld;
}
Flickable {
id: flickable;
anchors.fill : parent;
clip: true;
WebEngineView {
id: webView;
anchors.fill : parent;
scale: 1;
onLoadingChanged: {
if (loadRequest.status !== WebEngineView.LoadSucceededStatus) {
return;
}
flickable.contentHeight = 0;
flickable.contentWidth = flickable.width;
runJavaScript (
"document.documentElement.scrollHeight;",
function (actualPageHeight) {
flickable.contentHeight = Math.max (
actualPageHeight, flickable.height);
});
runJavaScript (
"document.documentElement.scrollWidth;",
function (actualPageWidth) {
flickable.contentWidth = Math.max (
actualPageWidth, flickable.width);
});
}
}
}
onUserDragImgEnabledChanged: {
if (userDragImgEnabled &&
(webView.loadRequest.status === WebEngineView.LoadSucceededStatus)) {
runJavaScript (revertCssJavaScript (kDisableUserDragCssId));
}
else {
webView.userScripts = currentUserScripts ();
}
}
onUserSelectEnabledChanged: {
if (userSelectEnabled &&
(webView.loadRequest.status === WebEngineView.LoadSucceededStatus)) {
runJavaScript (revertCssJavaScript (kDisableUserSelectCssId));
}
else {
webView.userScripts = currentUserScripts ();
}
}
function currentUserScripts () {
var userScriptsToSkip = [
disableUserDragScript.name,
disableUserSelectScript.name
];
var updatedUserScripts = [];
for (var i in webView.userScripts) {
var script = webView.userScripts[ i ];
if (-1 == userScriptsToSkip.indexOf (script.name)) {
updatedUserScripts.push (script);
}
}
if (!userDragImgEnabled) {
updatedUserScripts.push (disableUserDragScript);
}
if (!userSelectEnabled) {
updatedUserScripts.push (disableUserSelectScript);
}
return updatedUserScripts;
}
function applyCssJavaScript (selector, css, cssId) {
var applyCssJavaScript =
"(function () { \
cssElement = document.createElement ('style'); \
\
head = document.head || \
document.getElementsByTagName ('head')[ 0 ]; \
\
head.appendChild (cssElement); \
\
cssElement.type = 'text/css'; \
cssElement.id = '%1'; \
\
if (cssElement.styleSheet) \
{ \
cssElement.styleSheet.cssText = '%2 %3'; \
} \
else \
{ \
cssElement.appendChild ( \
document.createTextNode ('%2 %3')); \
} \
})();";
return applyCssJavaScript
.arg (cssId)
.arg (selector)
.arg (css);
}
function revertCssJavaScript (cssId) {
var revertCssJavaScript =
"(function () { \
var element = document.getElementById('%1'); \
\
if (element) { \
element.outerHTML = ''; \
\
delete element; \
} \
})()";
return revertCssJavaScript.arg (cssId);
}
}