QML學習:使用QML實現抽屜式側邊欄菜單

文章目錄

  • 前言
  • 一、環境配置
  • 二、實現步驟
  • 三、示例完整代碼
  • 四、注意事項
  • 總結


前言

最近在進行QML的學習,發現一個比較有意思的交互設計:抽屜式側邊欄菜單,出于開發實戰需求,最終實現了一個支持手勢拖拽、彈性動畫、蒙層效果和??智能懸停檢測??的抽屜菜單,下面將我的示例內容進行展示,以便大家學習,如有錯誤之處,歡迎大家批評指正。

項目效果
請添加圖片描述


提示:以下是本篇文章正文內容,下面案例可供參考

一、環境配置

我的示例使用的是Qt5.14版本,需要確保包含 ??Qt Quick Controls 2?? 模塊(安裝時勾選Qt Quick Controls 2組件),需要在項目的.pro文件中添加:

QT += qml quick quickcontrols2

這里有詳細的Qt安裝和QML項目的創建步驟:Qt Creator的安裝和Qml項目的創建
這里有QML的基礎教程:QML快速入門(Quick Starter)

二、實現步驟

1、基礎框架搭建

//通過ApplicationWindow創建主窗口
ApplicationWindow {id: mainWindowvisible: truewidth: 800height: 600title: "抽屜式菜單欄"......
}

2、頂部工具欄設計

//頂部工具欄
header: ToolBar {height: 50background: Rectangle {color: "#2196F3"   //藍色背景}......//這里實現了漢堡菜單按鈕,通過MouseArea檢測懸停狀態,并配合Timer實現??智能延時關閉??功能(詳細代碼見下文)......
}

3、抽屜菜單核心實現

//主內容區域
Item {id: mainContentanchors.fill: parent......//使用x坐標控制菜單位置,通過狀態機(States)切換展開/收起狀態,添加平滑動畫過渡效果(詳細代碼見下文)......
}

4、高級交互功能

//邊緣滑動手勢檢測,鼠標點擊左側區域后向右移動可以拉出菜單,雙擊也能展開菜單
MouseArea {id: drawerDragAreaanchors.left: parent.leftwidth: 20   //手勢檢測區域寬度height: parent.heightpropagateComposedEvents: true//拖拽起始位置的全局X坐標property real globalStartX: 0//鼠標按下事件處理onPressed: {globalStartX = mapToGlobal(mouseX, 0).xif(isDrawerOpen){mouse.accepted = false}}//位置變化事件處理onPositionChanged: {if (pressed) {//滑動距離超過25px時切換狀態let currentGlobalX = mapToGlobal(mouseX, 0).xlet delta = currentGlobalX - globalStartXif (Math.abs(delta) > 10) {mainWindow.isDrawerOpen = delta > 0}}}//添加雙擊切換onDoubleClicked: isDrawerOpen = !isDrawerOpen
}

三、示例完整代碼

1.main.qml

import QtQuick 2.14
import QtQuick.Controls 2.14ApplicationWindow {id: mainWindowvisible: truewidth: 800height: 600title: "抽屜式菜單欄"//當前選中的菜單項文本property string selectedMenuItem: "請選擇菜單項"//是否正在與菜單欄交互property bool isMenuActive: false//菜單欄是否展開property bool isDrawerOpen: false//菜單欄寬度property int drawerWidth: 200//根據窗口寬度自動調整菜單欄寬度Component.onCompleted: {drawerWidth = Qt.binding(() => Math.min(200, mainWindow.width * 0.8))}//頂部工具欄header: ToolBar {height: 50background: Rectangle {color: "#2196F3"   //藍色背景}Row {spacing: 20anchors.fill: parent//菜單入口按鈕ToolButton {id: menuButtonhoverEnabled: true   //啟用懸停檢測?//是否懸停在按鈕上property bool buttonHovered: false//按鈕內容contentItem: Text {text: "?"color: "white"font.pixelSize: 38}//鼠標交互MouseArea {anchors.fill: parenthoverEnabled: true//鼠標進入時展開菜單欄并修改懸停狀態onEntered: {isDrawerOpen = truemenuButton.buttonHovered = true}//鼠標離開時重置狀態并啟動關閉計時器onExited: {menuButton.buttonHovered = falseif (!mainWindow.isMenuActive) {timer.restart()}}}//點擊切換菜單欄狀態//onClicked: isDrawerOpen = !isDrawerOpen//自動關閉菜單欄定時器Timer {id: timerinterval: 300   //延時300ms關閉onTriggered: {//雙重驗證是否滿足關閉條件(未懸停在此按鈕及菜單欄中)if (!mainWindow.isMenuActive && !menuButton.buttonHovered) {isDrawerOpen = false}}}}//應用標題Label {text: "我的應用"color: "white"font.bold: truefont.pixelSize: 18anchors.verticalCenter: parent.verticalCenter}}}//主內容區域Item {id: mainContentanchors.fill: parent//中央文本顯示Text {id: contentTextanchors.centerIn: parenttext: mainWindow.selectedMenuItemfont.pixelSize: 24color: "#333333"}//遮罩層(展開菜單欄后出現)Rectangle {id: overlayanchors.fill: parentcolor: "#80000000"   //半透明黑色遮罩opacity: isDrawerOpen ? 1 : 0visible: opacity > 0enabled: visible//鼠標點擊關閉菜單欄MouseArea {anchors.fill: parentonClicked: isDrawerOpen = false}//創建平滑的透明度漸變效果Behavior on opacity {NumberAnimation {duration: 200easing.type: Easing.OutQuad}}}//抽屜菜單欄容器Rectangle {id: drawerwidth: drawerWidthheight: parent.heightx: -drawerWidth  // 初始隱藏位置color: "#ffffff"//菜單欄懸停檢測(注意這個需要放在ListView之前,否則動畫效果異常)MouseArea {anchors.fill: parenthoverEnabled: truepropagateComposedEvents: true   //允許事件繼續傳遞onEntered: mainWindow.isMenuActive = true//鼠標離開時重置狀態并啟動關閉計時器onExited: {mainWindow.isMenuActive = falsetimer.restart()}}//抽屜菜單列表ListView {anchors.fill: parentmodel: menuItems//菜單項模板delegate: ItemDelegate {id: menuItemwidth: drawerWidthheight: 50hoverEnabled: true//鼠標交互,處理懸停狀態MouseArea {anchors.fill: parenthoverEnabled: truepropagateComposedEvents: true//設置為false,允許事件傳遞給ItemDelegate,不攔截點擊事件onPressed: mouse.accepted = falseonEntered: mainWindow.isMenuActive = true//鼠標離開時重置狀態并啟動關閉計時器onExited: {//確保鼠標完全離開才更新狀態if(!containsMouse) {mainWindow.isMenuActive = falsetimer.restart()}}}//背景樣式background: Rectangle {color: menuItem.hovered ? "#2196F3" : "transparent"opacity: menuItem.hovered ? 0.6 : 0.3Behavior on color {ColorAnimation {duration: 150easing.type: Easing.OutCubic}}}//菜單項內容布局contentItem: Row {spacing: 10leftPadding: 10//圖標Image {source: model.iconwidth: 24height: 24anchors.verticalCenter: parent.verticalCenter}//文本Text {text: model.titlecolor: "#444444"font.pixelSize: 16anchors.verticalCenter: parent.verticalCenter}}//點擊事件處理onClicked: {console.log("切換到:", model.title)mainWindow.selectedMenuItem = model.title   //更新顯示文本isDrawerOpen = false   //點擊后自動關閉抽屜}}}//抽屜動畫狀態states: State {name: "opened"when: isDrawerOpenPropertyChanges {target: drawerx: 0}}//創建平滑緩動效果transitions: Transition {NumberAnimation {property: "x"duration: 300easing.type: Easing.InOutQuad}}}}//菜單項數據模型ListModel {id: menuItemsListElement { title: "首頁"; icon: "qrc:/icons/home.png" }ListElement { title: "消息"; icon: "qrc:/icons/message.png" }ListElement { title: "設置"; icon: "qrc:/icons/settings.png" }ListElement { title: "個人中心"; icon: "qrc:/icons/profile.png" }}//邊緣滑動手勢檢測MouseArea {id: drawerDragAreaanchors.left: parent.leftwidth: 20   //手勢檢測區域寬度height: parent.heightpropagateComposedEvents: true//拖拽起始位置的全局X坐標property real globalStartX: 0//鼠標按下事件處理onPressed: {globalStartX = mapToGlobal(mouseX, 0).xif(isDrawerOpen){mouse.accepted = false}}//位置變化事件處理onPositionChanged: {if (pressed) {//滑動距離超過25px時切換狀態let currentGlobalX = mapToGlobal(mouseX, 0).xlet delta = currentGlobalX - globalStartXif (Math.abs(delta) > 10) {mainWindow.isDrawerOpen = delta > 0}}}//添加雙擊切換onDoubleClicked: isDrawerOpen = !isDrawerOpen}
}

四、注意事項

1、資源路徑問題
其中菜單項數據模型中可以看到有圖標資源,需要確保圖標資源正確添加到.qrc文件,否則會顯示為空白,在項目的源文件目錄下添加了一個icons文件夾,其中有使用到的圖片資源:

2、事件沖突處理??
在代碼中可以看到設置mouse.accepted = false,允許事件傳遞,避免阻斷按鈕點擊事件


總結

這個示例中不僅實現了基礎的抽屜菜單,還加入了??手勢交互??、??智能懸停檢測等功能。可以看到QML的聲明式語法讓我們可以用少量代碼實現復雜的動態效果,本文中實現這個示例也是比較簡單的,要實現更復雜的功能還是需要不斷的學習哦~


hello:
共同學習,共同進步,如果還有相關問題,可在評論區留言進行討論。

參考文章:
Qt Creator的安裝和Qml項目的創建
QML快速入門(Quick Starter)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/78946.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/78946.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/78946.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

峰終定律——AI與思維模型【85】

一、定義 峰終定律思維模型是指人們對一段經歷的評價主要取決于這段經歷中的高峰時刻(無論是正向的還是負向的)以及結束時的感受,而不是整個經歷的平均感受。也就是說,如果在一段體驗的高峰和結尾階段給人們留下積極、強烈的印象…

【補題】Codeforces Round 664 (Div. 1) A. Boboniu Chats with Du

題意:給出n,d,m三個值,分別代表,有多少個值ai,使用超過m的ai,需要禁言d天,如果不足也能使用,m代表區分點,問能得到最大的值有多少。 思路: …

單片機與上位機串口通信:原理、應用與實踐

注:本文為 “單片機與上位機串口通信” 相關文章合輯。 略作重排,未整理去重。 如有內容異常,請看原文。 單片機與上位機的串行通信 饕餮 tt 于 2019 - 12 - 06 14:47:19 發布 寫在前面 本文主要記錄單片機通過 TXD、RXD 與上位機進行數據…

996引擎-人物模型(UIModel):創建內觀時裝備偏移問題

996引擎-人物模型(UIModel):創建內觀時裝備偏移問題 創建 人物模型(UIModel)問題參考資料創建 人物模型(UIModel) 90、91 是自定義劍甲的穿戴位置,因為需求只需要顯示劍甲,所以下面創建人物模型時,只給了劍甲的id、特效。 function Controller:updateUI()-- 自定義收拾…

Python小程序:上班該做點摸魚的事情

系統提醒 上班會忘記一些自己的事,所以你需要在上班的的時候突然給你彈窗,你就知道要做啥了 源碼 這里有一個智能家居項目可以看看(開源) # -*- coding:utf-8 -*- """ 作者:YTQ 日期: 2025年04日29 21:51:24 """ impor…

centos安裝部署配置kafka

1、解壓到目錄 tar -zxvf kafka_2.13-2.8.2.tgz -C /usr/local/kafka2.進入目錄 cd /usr/local/kafka/kafka_2.13-2.8.23.查看版本(驗證是否已解壓) bin/kafka-topics.sh --version4.修改配置,注意:此配置中有一個默認的zookee…

深?理解指針(7)

1.函數指針變量的創建 在x86環境下: 我們發現:以函數是有地址的,函數名就是函數的地址,當然也可以通過& 函數名 的?式獲得函數的地址。 如果我們要將函數的地址存放起來,就得創建函數指針變量咯,函數…

AdaBoost算法的原理及Python實現

一、概述 AdaBoost(Adaptive Boosting,自適應提升)是一種迭代式的集成學習算法,通過不斷調整樣本權重,提升弱學習器性能,最終集成為一個強學習器。它繼承了 Boosting 的基本思想和關鍵機制,但在…

《PyTorch documentation》(PyTorch 文檔)

PyTorch documentation(PyTorch 文檔) PyTorch is an optimized tensor library for deep learning using GPUs and CPUs. (PyTorch是一個優化的張量庫,用于使用GPU和CPU進行深度學習。) Features described in this documentation are classified by release status: (此…

Android學習總結之算法篇六(數組和棧)

括號匹配 public static boolean isValid(String s) {// 創建一個棧用于存儲左括號Stack<Character> stack new Stack<>();// 遍歷字符串中的每個字符for (char c : s.toCharArray()) {if (c ( || c [ || c {) {// 如果是左括號&#xff0c;將其壓入棧中stack…

遺傳算法(Genetic Algorithm,GA)

遺傳算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;是一種受生物進化理論啟發的優化算法&#xff0c;通過模擬自然選擇和遺傳機制來搜索復雜問題的最優解。 ??核心原理?? ??自然選擇與適者生存??&#xff1a;適應度高的個體更有可能繁殖&#xff0c;將…

消防應急物資智能調用立庫:豪越科技助力消防“速戰速決”

在消防救援的戰場上&#xff0c;時間就是生命&#xff0c;每一秒都關乎著人民群眾的生命財產安全。然而&#xff0c;在過去的緊急救援中&#xff0c;應急物資無法及時到位的情況時有發生&#xff0c;成為制約救援效率的關鍵難題&#xff0c;給救援工作帶來了巨大的困境。 想象一…

【MySQL】數據類型和表的操作

目錄 一. 常用的數據類型 1.數值類型 1.1 整形類型 1.2 浮點型類型 2.字符串類型 char和varchar的區別 如何選擇char和varchar 3.日期類型 4.二進制類型 二. 表的操作 1.查看所有表 2.表的創建 3.查看表的結構 4.表的修改 4.1 添加新的列 4.2 修改表中現有的列 4…

漲薪技術|0到1學會性能測試第43課-apache status模塊監控

前面的推文我們認識了apache目錄結構與配置知識,今天我們繼續來看下apache監控技術,究竟是怎么做性能監控的。后續文章都會系統分享干貨,帶大家從0到1學會性能測試。 Apache監控技術 關于apache監控通常會有兩種方法: 一是:使用apache自帶的status監控模塊進行監控; 二是…

關于 MCP 的理論知識學習

文章目錄 1. 寫在最前面2. 基本概念2.1 Why MCP2.1.1 大模型訪問的局限2.1.2 過渡階段—Function Call2.1.3 當前階段— MCP 3. 碎碎念4. 參考資料 1. 寫在最前面 最近有一項任務是寫舊版本遷移到新版本的支持文檔&#xff0c;文檔的編寫是借助于 cursor 幫忙寫的。但是實現的…

C++學習之路,從0到精通的征途:List類的模擬實現

目錄 一.list的介紹 二.list的接口實現 1.結點 2.list結構 3.迭代器 &#xff08;1&#xff09;begin &#xff08;2&#xff09;end 4.修改 &#xff08;1&#xff09;insert &#xff08;2&#xff09;push_back &#xff08;3&#xff09;push_front &#xff0…

【游戲ai】從強化學習開始自學游戲ai-2 使用IPPO自博弈對抗pongv3環境

文章目錄 前言一、環境設計二、動作設計三、狀態設計四、神經網路設計五、效果展示其他問題總結 前言 本學期的大作業&#xff0c;要求完成多智能體PPO的乒乓球對抗環境&#xff0c;這里我使用IPPO的方法來實現。 正好之前做過這個單個PPO與pong環境內置的ai對抗的訓練&#…

計算機考研精煉 操作系統

第 14 章 操作系統概述 14.1 基本概念 14.1.1 操作系統的基本概念 如圖 14 - 1 所示&#xff0c;操作系統是計算機系統中的一個重要組成部分&#xff0c;它位于計算機硬件和用戶程序&#xff08;用戶&#xff09;之間&#xff0c;負責管理計算機的硬件資源&#xff0c;為用戶和…

什么是基爾霍夫第一定律

基爾霍夫第一定律&#xff08;Kirchhoffs First Law&#xff09;&#xff0c;也稱為基爾霍夫電流定律&#xff08;Kirchhoffs Current Law&#xff0c;簡稱 KCL&#xff09;&#xff0c;是電路分析中最基礎的定律之一。它描述了電路中電流的守恒特性&#xff0c;適用于任何集總…

解決 RN Switch 組件在安卓端樣式很丑的問題

解決此種問題的方式有很多 可以導入原生庫react-native-switch 切圖 (會缺少動畫) 使用 js 組件 這里使用 js 繪制組件&#xff08;原生體驗&#xff09;解決此類問題 Switch.tsx import React, { useEffect, useRef, useState } from react; import { Animated, Pressabl…