本文介绍了QML WebEngine查看弹幕内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 QML 和 WebEngineView 组件为带有 Ubuntu 14.04 的桌面制作一个简单的 Web 浏览器.该应用程序将在带有触摸板的设备上运行,因此最好让 WebEngineView 中显示的内容可滑动.

I'm trying to make a simple web-browser for desktop with Ubuntu 14.04 using QML and WebEngineView component. The application will be working on devices with touchpad so it would be nice to make the content displayed inside WebEngineView flickable.

我尝试过这样做,但它不起作用:

I tried to do it this way, but it does not work:

...
        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
            }
       }
...

如果您对此有任何想法或经验,请提供帮助!

If you have any idea's or experience with this, please help!

推荐答案

我想做 WebEngineView 也可以轻弹.我决定,最好使用 Flickable.但是天真的做法是:

I wanted to make WebEngineView flickable too. I decided, that it's better to do it using Flickable. But naive approach of making something like:

...
Flickable {
    WebEngineView {...}
}
...

不会工作.

进一步调查使我发现基于 Qt 的嵌入式触摸设备 Web 浏览器.我已经在我的电脑上试过了.看起来它完全符合我的要求,但它太复杂了,而且 GPL 许可使它无法用于任何用途.

Further investigation led me to Qt based Web browser for embedded touch devices. I have tried it out on my PC. It seems like it's doing exactly what I want, but it's too complicated and GPL license renders it useless for any kind of use.

经过一些实验,我发现如果 Flickable.contentHeightFlickable.contentWidth 至少与 WebEngineView 显示的网页的实际大小相匹配.Flickable 的这些属性可能具有比实际页面大小更大的值.在这种情况下,您将能够超越页面内容.如果 Flickable.contentHeight 和/或 Flickable.contentWidth 小于页面大小,您仍然可以轻弹.是否要这样由你决定)

After some experiments I found out that flicking will work if Flickable.contentHeight and Flickable.contentWidth at least match the actual size of Web page being shown by WebEngineView. Those properties of Flickable may have greater values than actual page size have. In this case you'll be able to flick beyond content of page. If Flickable.contentHeight and/or Flickable.contentWidth are less than page size you'll still be able to flick. It's up to you whether you want it this way or not)

所以它最终获得了显示的实际页面大小并将其设置为 Flickable.contentHeight 和 Flickable.contentWidth.我在这里给你一个简短的故事:没有办法使用 WebEngineView API 获得所需的值(或者至少我在 Qt 5.7/5.8 文档中没有找到任何东西).但我不小心发现了 这个答案在 SO 上.使用这个答案,我设法使一切正常:

So it ended up to acquiring actual page size shown and setting it as Flickable.contentHeight and Flickable.contentWidth. I'll give you a short story here: there is no way to get desired values with WebEngineView API (or at least I didn't find anything in Qt 5.7/5.8 documentation). But I've accidentally found this answer on SO. Using this answer I've managed to make everything work:

...
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);
                })
        }
    }
}
...

上面截取的代码可能需要一些调整,但它几乎是我拥有的代码的副本.

The code snipped above may need some adjustments but it's nearly a copy of the code I have that works.

UPD 1:我发现这不是最终的解决方案,因为在加载新页面后由于某种原因 document.documentElement.scrollWidth 可能不会重置并保持与上一页相同.

UPD 1: I have found out that this is not the final solution, because for some reason after new page is loaded document.documentElement.scrollWidth may not be reset and remain the same it was for previous page.

UPD 2:我已经解决了上述问题,但解决方案有点难看:将 WebEngineView.onLoadingChanged 中的 Flickable.contentWidth 重置为 Flickable.width.将 Flickable.contentWidth 设置为 0 会导致加载后内容高度过大.

UPD 2: I've resolved the aforementioned problem, but the solution is a bit ugly: reset Flickable.contentWidth in WebEngineView.onLoadingChanged to Flickable.width. Setting Flickable.contentWidth to 0 will result in inappropriately large height of content after loading.

我所做的另一项调整是取消了对 100% 加载状态的要求.

Another adjustment I've made was removing of requirement for 100% loading state.

UPD 3:可滑动 WebEngiveView 的更完整版本.使用用户脚本而不是直接调用 JavaScript,因为我遇到了一些奇怪的错误,后者导致 WebEngineView 关闭.

UPD 3: A more complete version of the flickable WebEngiveView. User scripts are used instead of directly invoking JavaScript because I encountered some strange errors with the latter that resulted in WebEngineView closing.

// 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 <[email protected]>
//
// 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 WebEngine查看弹幕内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-27 22:48