QML WebEngineView 轻弹内容

2024-01-03

我正在尝试使用 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
            }
       }
...

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


我想做Web引擎视图 http://doc.qt.io/qt-5/qml-qtwebengine-webengineview.html也可以轻弹。我决定,最好使用可轻弹 http://doc.qt.io/qt-5/qml-qtquick-flickable.html。但做出这样的事情的天真方法:

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

不管用。

进一步的调查使我发现用于嵌入式触摸设备的基于 Qt 的 Web 浏览器 http://code.qt.io/cgit/qt-apps/qtwebbrowser.git/。我已经在我的电脑上尝试过了。看起来它正在做我想要的事情,但它太复杂了,而且 GPL 许可证使其无法用于任何用途。

经过一些实验,我发现轻拂会起作用,如果Flickable.contentHeight http://doc.qt.io/qt-5/qml-qtquick-flickable.html#contentHeight-prop and Flickable.contentWidth http://doc.qt.io/qt-5/qml-qtquick-flickable.html#contentWidth-prop至少匹配 WebEngineView 显示的网页的实际大小。 Flickable 的这些属性可能具有比实际页面大小更大的值。在这种情况下,您将能够轻拂页面内容之外的内容。如果 Flickable.contentHeight 和/或 Flickable.contentWidth 小于页面大小,您仍然可以轻拂。这取决于你是否想要这样)

因此它最终获取显示的实际页面大小并将其设置为 Flickable.contentHeight 和 Flickable.contentWidth。我在这里给你一个小故事:没有办法使用 WebEngineView API 获取所需的值(或者至少我在 Qt 5.7/5.8 文档中没有找到任何内容)。但我无意中发现这个答案关于SO https://stackoverflow.com/questions/26278858/how-to-get-the-contentsize-of-a-web-page-in-qt5-4-qtwebengine。使用这个答案,我成功地使一切正常工作:

...
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 <[email protected] /cdn-cgi/l/email-protection>
//
// 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);
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QML WebEngineView 轻弹内容 的相关文章

  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • 调整 QML 图像显示尺寸

    我有一个带有嵌套的 QML 窗口RowLayout 在内排我有两个图像 来源 png这些图像的文件 故意 相当大 当我尝试设置height这些图像上的属性使它们变小 但它们仍然被画得很大 Desired Appearance Actual
  • 安装多个版本的 Qt 库

    我在windows中安装了QtSDK 它的Qt库版本是4 7 0 现在我想为 mingw 和 VS2008 安装 Qt 库版本 4 8 2 我怎样才能做到这一点 如何向QtCreator引入多个版本 注意 我已经从以下位置下载了库http
  • MAC 上的 QT/C++ - 未设置应用程序图标

    我正在努力解决的奇怪问题 在与我的 pro QT 项目文件相同的文件夹中 我有一个 Resources myIcon png 我试图将其设置为我构建的应用程序的图标 在 OSX 上运行 我阅读了文档 它建议在 pro 文件中添加 ICON
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • QGraphicsView 和 eventFilter

    这个问题已经困扰我两天多了 所以我想我应该问一下 我在Win7上使用Qt 4 5 3 用VC2008编译 我有 MyGraphicsView 继承 QGraphicsView 和 MyFilter 继承 QObject 类 当我将 MyFi
  • 如何在 Qt-Embedded 中(正确)输出多语言文本?

    我的目标系统是 linux 3 3 7 Qt Embedded 开源版 4 8 Droid 字体 取自 fonts droid 20111207 git 1 all deb Debian 软件包并复制到 usr lib fonts目录 主要
  • Qt/c++ 随机字符串生成[重复]

    这个问题在这里已经有答案了 我正在创建一个应用程序 需要生成多个随机字符串 几乎就像一个由一定长度的 ASCII 字符组成的唯一 ID 这些字符混合有大写 小写 数字字符 有没有 Qt 库可以实现这一点 如果没有 在纯 C 中生成多个随机字
  • 有没有办法在没有 QApplication::exec() 的情况下使用 Qt?

    有没有一种安全的方法可以在不调用 QApplication exec 的情况下使用 Qt 我有许多不同的对象正在对多个资源执行长期进程 至少其中一个正在与 Web 应用程序服务器进行通信 我正在制作一个 GUI 应用程序 提示用户在正确的时
  • 程序意外完成 - QT Creator

    我正在尝试使用 QT Creator 使用 QT 框架开发 GUI 控制台应用程序 我使用的是Windows XP 我安装了QT 4 8 3和mingw 两者均已安装 没有任何错误 然后我安装了QT Creator QT 版本 路径中的 Q
  • QT/QML Android App,点击通知栏时打开应用程序

    我为 Android 应用程序制作了一个 QT 当我单击平板电脑中上面看到的按钮通知栏时 但是 如果单击通知 我的应用程序将打开 聚焦 不知道 并显示黑色窗口 简单来说怎么做呢 我的代码是 package org ays operation
  • (如何)我可以抑制未找到包配置文件的警告吗?

    我正在尝试创建一个CMakeLists txt尝试查找的文件Qt5 如果失败 则尝试回退到Qt4安装 该脚本到目前为止有效 但如果出现以下情况我总会收到警告Qt5未安装 注意FindQt5 cmake是由提供Qt5并且仅当以下情况时才可用Q
  • GoQt 致命错误:QAbstractAnimation:没有这样的文件或目录

    我尝试编译 Qt 来开发桌面应用程序 我按照 Qt 网站上的官方 wiki 指南的说明进行操作 当我尝试go run示例文件夹中的示例 我收到错误 去运行 home pinkya rabbit workspace go1programs s
  • QTcpSocket 有时不发送数据

    我有两个 QT 应用程序 一个应用程序可以被认为保存了大数据 它每秒向第二个应用程序发送大约 10 KB 的数据块 之前我尝试使用QUdpSocket来传输数据 但由于MTU限制在2 5K左右 并且需要自己分割和重新组合数据 所以我改用QT
  • 从布局中按名称获取小部件

    如果我想从 python Qt 的布局中获取特定的小部件 我应该如何进行 到目前为止我所做的 for i in range self ui horizontalLayout 14 count here it does fail name s
  • 在 Qt5 中,是否需要 Q_INVOKABLE 来从 QML 调用公共 QObject 函数?

    我刚刚意识到我可以调用暴露于 QML 的对象的几乎任何函数 现在我对 Q INVOKABLE 很好奇 Qt5docs http doc qt io qt 5 qtqml cppintegration exposecppattributes
  • 如何在 Qt 中以编程方式制作一条水平线

    我想弄清楚如何在 Qt 中制作一条水平线 这很容易在设计器中创建 但我想以编程方式创建一个 我已经做了一些谷歌搜索并查看了 ui 文件中的 xml 但无法弄清楚任何内容 ui 文件中的 xml 如下所示
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • 如何获取 QTableView 的标题列表?

    我有一个QTableView我的对话框中的对象 我需要访问该表的水平标题并将它们放入QStringList object 尽管进行了大量搜索 但我在 Qt 文档中找不到如何获取此标头列表 编辑 我发现的最接近的地方是this https w

随机推荐

  • 如何在 Rails 中将文本转换为 unicode?

    在我的数据库中 我有以下条目 id name info 1 John Smith 正如您所知 信息栏显示错误 但它实际上是韩语 在 Chrome 中 当我将浏览器编码从 UTF 8 切换为韩语 我认为是 euc kr 时 我实际上设法这样查
  • 如何安装jar库?

    我已经下载了 ANTLR Java 运行时库 这是一个 jar 文件 它包含 org antlr runtime 我应该把它放在哪里以便 Java 编译器可以找到它 我需要提取它吗 如果相关的话 我正在使用 NetBeans 目前 假设您可
  • msbuild xmlupdate 删除 web.config 中的节点

    如何使用 MSBuild 社区任务删除 web config 中的节点 我可以使用 XmlUpdate 任务更新节点 但无法删除节点 有任何想法吗 XmlUpdate 任务可以做到这一点 我正在使用 2010 年 11 月 30 日的夜间版
  • 将纬度和经度转换为 3D 空间中的点

    我需要将纬度和经度值转换为 3 维空间中的点 我已经尝试了大约 2 个小时 但没有得到正确的结果 The 等长方形坐标来自openflights org http openflights org data html 我尝试了几种组合cos
  • JIRA api 的 .NET 包装器?

    我正在开发 JIRA 实现 需要使用 API 有谁知道 JIRA SOAP API 的现有 NET 包装器吗 在 Visual Studio NET 项目中 右键单击项目引用并选择 添加服务引用 输入 JIRA 的 WSDL 描述符的 UR
  • 如何捕获datePicker关闭事件

    我正在使用日期选择器 它工作正常 我的网页很少需要使用开始日期和结束日期进行一些计算 我希望能够在日期选择器关闭时进行计算 我在用 有人有什么建议吗 您正在寻找onClose method 参考API文档here http api jque
  • 公共 IP 地址是否可以用作 Google OAuth 重定向 URI?

    我正在尝试设置一个需要用户的 Google Latitude 信息的网络服务 因此我使用 Google OAuth 来获取用户授权内容 但是 当尝试在 Google API 控制台中为 Web 应用程序客户端 ID 设置重定向 URI 时
  • 在 int main() 中使用类函数

    我在从主程序调用函数时遇到问题 这些功能必须在我的班级中 如何从 int main 访问它们 include
  • 使用 Delphi 7 进行开发时,准备好使用 Delphi 2009 及更高版本了吗?

    我正在 Delphi 7 中开发一个 Word 插件 但很快我会将其升级到 Delphi 2010 如您所知 因为 2009 版本 Delphi 引入了新的字符串类型Unicode字符串等于关键字string 另一方面 根据这个线程 htt
  • 使用 AJAX 调用 WordPress 简码

    我想使用切换按钮运行短代码 如果开关为 ON 我会调用一个短代码 如果它为 OFF 我会调用另一个 作为测试 我尝试通过 AJAX 单击单个链接来调用短代码 它给出了以下内容 文件 page recherche php a href CLI
  • gitlab CI期间激活conda环境

    My gitlab ci yml文件看起来像这样 anomalydetector image continuumio miniconda 4 7 10 stage build tags docker script conda env cre
  • 是否可以在 Xcode 7 自动化 UI 测试中存根 HTTP 请求?

    我一直在尝试在 Xcode 7 自动化 UI 测试中拦截和存根 模拟 HTTP 请求 使用诸如OHHTTP存根 https github com AliSoftware OHHTTPStubs 没有运气 下面是我如何尝试在 UI 测试文件的
  • 如何在 Tomcat 8.5 中部署 Spring boot 时使用外部配置文件

    我的 Spring Boot 应用程序 2 1 1 RELEASE 作为 WAR 部署在 Debian 9 系统下的 Tomcat 8 5 服务器中 除其他外 它使用以下文件来配置应用程序 myApplication properties
  • 快速滚动带有图像的表格单元格。是这样的吗?

    我尝试使用 Tweetie 的创建者 Loren Brichter 的创建一个快速滚动列表技术 http web archive org web 20100922230053 http blog atebits com 2008 12 fa
  • AWS EBS 卷“使用中 - 优化”

    我有一个 EBS 卷显示 使用中 优化 状态 这是什么意思 AWS正在执行哪些优化 它位于附加到 Windows Server 2012 R2 EC2 实例的 300GB 加密 gp2 卷上 The in use optimizing状态与
  • 将 NLP 转换为 SQL 有哪些方法? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 最近 我们开始研究对话式聊天机器人的想法 并一直在考虑将自然语言查询转换为 SQL 的不同方法 这些是
  • C#,输出多个值的方法

    我正在使用c 我有一个输出多个值的方法 我知道out但这是一个引用类型 是否有与值类型等效的东西 但也可以从方法输出多个值 对于引用类型 值也会在方法之外发生更改 因此我想防止这种情况发生 out 我知道out但这是一个引用类型 不清楚你的
  • Python格式大小应用(将B转换为KB、MB、GB、TB)

    我正在尝试编写一个应用程序来将字节转换为 kb 到 mb 到 gb 到 tb 这是我到目前为止所拥有的 def size format b if b lt 1000 return i b B elif 1000 lt b lt 100000
  • 在 Postgresql 中,如何使用“At Time Zone”取消反转时区偏移

    我正在尝试了解 Postgresql 时区 但我似乎无法弄清楚这一点 EST 是美国的 东部标准时间 通常是UTC 5 http en wikipedia org wiki Eastern Time Zone 示例 1 基础测试 selec
  • QML WebEngineView 轻弹内容

    我正在尝试使用 QML 和 WebEngineView 组件使用 Ubuntu 14 04 制作一个简单的桌面网络浏览器 该应用程序将在带有触摸板的设备上运行 因此最好使 WebEngineView 中显示的内容可滑动 我尝试这样做 但它不