QML使用滚轮/触控板实现水平滚动/垂直滚动/缩放功能

news2024/11/27 0:20:43

目录

  • 引言
  • 核心代码
  • 完整代码

引言

因为项目需要需要进行组件移动、缩放的开发,具体要求如下:

  1. 鼠标滚轮,实现垂直移动
  2. Ctrl+鼠标滚轮,实现缩放
  3. Alt+鼠标滚轮,实现水平移动
  4. 触控板移动,实现垂直、水平移动
  5. 触控板双指,实现缩放

在这里插入图片描述

核心代码

实现上述功能主要使用到两个组件MouseArea、PinchArea,MouseArea主要是进行鼠标事件的操作和部分触控板事件的操作,PinchArea主要是Mac下识别触控板的双指缩放。需要注意的是鼠标滚轮垂直移动和触控板垂直移动手势是混合在一起的,可以通过wheel.angleDelta.y是否为120的倍数去判断,如下所示:

	if (wheel.angleDelta.y && !(wheel.angleDelta.y % 120)) {
		// ...
	}
	else {
		// ...
	}

上述功能中需要识别Ctrl、Alt按键是否按下,需要通过wheel事件的modifiers 属性进行判断,如下所示:

MouseArea {
	onWheel: {
		if (wheel.modifiers & Qt.AltModifier) {
    		//..
		}
		else if (wheel.modifiers & Qt.ControlModifier) {
     		//..               
		}
		else {
			//..
		}
	}
}

完整代码

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    id: root
    width: 640
    height: 480
    visible: true

    //title: qsTr("Hello World")
    Rectangle {
        id: rect
        width: 100
        height: 100
        x: (parent.width - width) / 2
        y: (parent.height - height) / 2
        color: "blue"
    }

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    PinchArea {
        // Mac手势使用
        id: pinchArea
        anchors.fill: parent
        pinch.maximumScale: 20
        pinch.minimumScale: 0.2
    }

    Connections {
        target: mouseArea

        function onWheel(wheel) {
            if (wheel.pixelDelta === Qt.point(0, 0)
                    && wheel.angleDelta === Qt.point(0, 0)) {
                return
            }

            //console.log("wheel.angleDelta", wheel.angleDelta)
            //console.log("wheel.pixelDelta", wheel.pixelDelta)

            if (Qt.platform.os == "windows") {
                // Windows处理
                if (wheel.modifiers & Qt.AltModifier) {
                    // 左右滚动
                    if (wheel.angleDelta.x > 0) {
                        // 往左滚动
                        rect.x = Math.max(rect.x - 50, 0)
                    }
                    else {
                        // 往右滚动
                        rect.x = Math.min(rect.x + 50, root.width - rect.width)
                    }
                }
                else if (wheel.modifiers & Qt.ControlModifier) {
                    // 缩放
                    if (wheel.angleDelta.y > 0) {
                        rect.scale = Math.min(rect.scale + 0.1, 2)
                    }
                    else {
                        rect.scale = Math.max(rect.scale - 0.1, 1)
                    }
                }
                else {
                    if (wheel.angleDelta.y && !(wheel.angleDelta.y % 120)) {
                        // 鼠标滚动
                        if (wheel.angleDelta.y > 0) {
                            // 向上滚动
                            rect.y = Math.max(rect.y - 50, 0)
                        }
                        else {
                            // 向下滚动
                            rect.y = Math.min(rect.y + 50, root.height - rect.height)
                        }
                    }
                    else {
                        // 触摸板滚动
                        let tempX = rect.x - wheel.angleDelta.x
                        tempX = Math.max(tempX, 0)
                        tempX = Math.min(tempX, root.width - rect.width)
                        rect.x = tempX

                        let tempY = rect.y + wheel.angleDelta.y
                        tempY = Math.max(tempY, 0)
                        tempY = Math.min(tempY, root.height - rect.height)
                        rect.y = tempY
                    }
                }
            }
            else {
                // Mac处理
                if (wheel.modifiers & Qt.AltModifier) {
                    // 左右滚动
                    if (wheel.angleDelta.y > 0) {
                        // 往左滚动
                        rect.x = Math.max(rect.x - 50, 0)
                    }
                    else {
                        // 往右滚动
                        rect.x = Math.min(rect.x + 50, root.width - rect.width)
                    }
                }
                else if (wheel.modifiers & Qt.ControlModifier) {
                    // 缩放
                    if (wheel.angleDelta.y > 0) {
                        rect.scale = Math.min(rect.scale + 0.1, 2)
                    }
                    else {
                        rect.scale = Math.max(rect.scale - 0.1, 1)
                    }
                }
                else {
                    if (wheel.angleDelta.y && !(wheel.angleDelta.y % 120)) {
                        // 鼠标滚动
                        if (wheel.angleDelta.y > 0) {
                            // 向上滚动
                            rect.y = Math.max(rect.y - 50, 0)
                        }
                        else {
                            // 向下滚动
                            rect.y = Math.min(rect.y + 50, root.height - rect.height)
                        }
                    }
                    else {
                        // 触摸板滚动
                        let tempX = rect.x + wheel.pixelDelta.x
                        tempX = Math.max(tempX, 0)
                        tempX = Math.min(tempX, root.width - rect.width)
                        rect.x = tempX

                        let tempY = rect.y + wheel.pixelDelta.y
                        tempY = Math.max(tempY, 0)
                        tempY = Math.min(tempY, root.height - rect.height)
                        rect.y = tempY
                    }
                }
            }
        }
    }

    Connections {
        target: pinchArea

        property double oriScale: 1

        function onPinchStarted(pinch) {
            oriScale = rect.scale
        }

        function onPinchUpdated(pinch) {
            let tempScale = pinch.scale * oriScale
            tempScale = Math.min(tempScale, 2)
            tempScale = Math.max(tempScale, 1)
            rect.scale = tempScale
        }

        //function onPinchFinished(pinch) {
        //    rect.scale = pinch.scale * oriScale
        //    console.log("onPinchFinished", pinch.scale)
        //}
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/781987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#事件学习笔记

一.事件概述: 事件的作用是降低模块间的耦合度,本质是观察者模式的应用,通过增加监听器,使事件响应函数的调用分散在各个对象自身内部,当增加和减少一个事件响应函数时,只需要增加或删除相应对象内的代码&…

MyBatis-Plus 的基础增删改查

目录 1. 简介 2. 准备工作 3. MyBatis-Plus 实现增删改查 1. MyBatis-Plus 简介 MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生. 2. 准备工作 2.1 准备数据表 D…

ArgoCD结合Gitlab交付项目到kubernetes集群

ArgoCD结合Gitlab交付项目到kubernetes集群 作者:行癫(盗版必究) 一:环境准备 1.kubernetes集群环境 2.HA_Argocd环境 3.Gitlab集群环境 二:项目配置 1.配置Gitlab 创建仓库,并写入yaml文件,利用yaml构建application;此案例结合了NFS实现持久化存储

【ARM Coresight 系列文章 10.2 - ARM Coresight STM Trace packets】

文章目录 Trace protocolpacket的种类Error packetsVERSION Packets同步 packet 上篇文章:ARM Coresight 系列文章 10.1 - ARM Coresight STM 介绍及使用 Trace protocol STM 产生的trace的是遵守 MIPI System Trace Protocol version 2 (STPv2) 规范的&#xff0c…

Windows环境下Elasticsearch相关软件安装

Windows环境下Elasticsearch相关软件安装 本文将介绍在 windows 环境下安装 Elasticsearch 相关的软件。 1、安装Elasticsearch 1.1 安装jdk ElasticSearch是基于lucence开发的,也就是运行需要java jdk支持,所以要先安装JAVA环境。 由于ElasticSear…

【C++】深入剖析list

本期我们来深入list的实现原理: 目录 一、STL中的list 二、list的模拟实现 2.1 搭建list的框架 2.2 list迭代器的实现 2.2.1 普通迭代器的实现 2.2.2 const类型迭代器的实现 2.2.3 迭代器中->运算符重载实现 2.3 其他功能函数的实现 2.3.1 insert 2.…

爬虫小白-如何辨别是否有cookie反爬案例

目录 一、Cookie介绍二、cookie生成来源区分查找三、如何判断是否有cookie反爬四、来自服务器生成的cookie反爬解决方法五、来自js生成的cookie反爬解决方法 一、Cookie介绍 先推荐该篇文章简单了解Cookie、Session、Token、JWT1、cookie的类型:会话cookie和持久co…

【LeetCode热题100】打卡第42天:滑动窗口最大值搜索二维矩阵II

文章目录 【LeetCode热题100】打卡第42天:滑动窗口最大值&搜索二维矩阵II⛅前言 滑动窗口最大值🔒题目🔑题解 搜索二维矩阵II🔒题目🔑题解 【LeetCode热题100】打卡第42天:滑动窗口最大值&搜索二维…

装箱问题(背包问题)

题目描述 有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 (正整数)。要求从 n 个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。 输入格式 第一行,一个整…

js函数增强

目录 函数的属性arguments将arguments转换成数组rest 纯函数柯里化函数自动实现函数柯里化组合函数自动实现组合化with与evalwitheval 严格模式严格模式的限制 函数的属性 函数其实也是一个对象 是对象就会有对应的方法与属性 以下是几个常用属性 name name属性主要用于访问给…

vue 富文本图片回显

富文本上传 <el-form-item label"服务费打款银行回单" prop"bankreceipt"> <!-- <ImageUpload--> <!-- :value"form.bankreceiptUrl"--> <!-- :fileType"fileType"--> <…

【解决方案】视频传输方案怎样选择适用的WiFi模块

工作环境中&#xff0c;我们接触的最多的是有线传输&#xff0c;但是这个会因为转换接口、传输距离等原因受到一些限制&#xff0c;而无线传输不会&#xff0c;不需要布线&#xff0c;不限制接口&#xff0c;传输距离也由于有线传输&#xff0c;这也是物联网广泛使用无线通信技…

了解下余弦相似度在文本处理中的应用

大家好啊&#xff0c;我是董董灿&#xff01; 昨天写了一篇介绍词向量的文章&#xff1a;5分钟搞懂什么是词嵌入&#xff0c;里面说到&#xff1a;通过把文本转换为词向量&#xff0c;就可以十分方便的计算两者之间的关系&#xff0c;看看哪两个单词更为相近。 比如有四个单词…

AtCoder Beginner Contest 288 F. Integer Division(递推+前缀和优化dp)

题目 给定一个n(2<n<2e5)位的数字串X&#xff0c; 可以将X划分成若干段&#xff0c;得分为每一段的乘积&#xff08;可以不分割&#xff0c;此时得分为X&#xff09; 求所有种分法的得分之和&#xff0c;答案对998244353取模 思路来源 洛谷题解 [ABC288F] Integer …

【PostgreSQL内核学习(十)—— 查询执行(可优化语句执行)】

可优化语句执行 概述物理代数与处理模型物理操作符的数据结构执行器的运行 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明引用来源。 本文主要…

SAP客制化区域菜单和IMG配置清单

1. 自定义区域菜单 事务代码 SE43&#xff0c;操作如下 添加菜单对象 展示效果 输入区域菜单名称并回车&#xff0c;效果如下 2. 自定义IMG配置 事务代码 SIMGH IMG structure 示例-事务代码入口 示例-表格维护入口 示例-自定义代码控制对象 需要创建dummy表并设置表维护 页面设…

平头哥TH5120 BeagleV-Ahead开机系统软件使用体验

等了许久&#xff0c;Beagle 社区官网终于上线了BeagleV-Ahead 的主页 网址 https://beagleboard.org/beaglev-ahead &#xff0c;我们的系统软件评测将会以这个官方主页为出发点 &#xff0c;进行一系列的系统软件功能等操作演示&#xff0c;因官网没有中文页面&#xff0c;我…

【雕爷学编程】Arduino动手做(168)---ATTINY85迷你USB开发板2

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

瑞吉外卖开发笔记 二

1、完善登录功能 问题分析 前面我们已经完成了后台系统的员工登录功能开发&#xff0c;但是还存在一个问题:用户如果不登录&#xff0c;直接访问系统首页面&#xff0c;照样可以正常访问。 这种设计并不合理&#xff0c;我们希望看到的效果应该是&#xff0c;只有登录成功后…

JVM运行时数据区——字符串常量池位置的调整

在JDK6及之前&#xff0c;使用永久代来实现方法区&#xff0c;字符串常量池(StringTable)是在永久代(方法区)中的&#xff0c;但是方法区的回收效率不高&#xff0c;在Full GC时才会回收。 在JDK7中&#xff0c;将字符串常量池转移到了堆中&#xff0c;分配在年轻代和老年代中。…