[Qt6][QML][教程]QML创建一个漂亮的音乐显示弹窗

您所在的位置:网站首页 qt设置弹窗 [Qt6][QML][教程]QML创建一个漂亮的音乐显示弹窗

[Qt6][QML][教程]QML创建一个漂亮的音乐显示弹窗

2023-04-13 16:18| 来源: 网络整理| 查看: 265

1. 前言

以前的弹窗效果有些看腻了,这次更新下界面。

教程被应用在MediaStateT中, Tag v1.5

MediaStateT Github项目地址: https://github.com/taxue-alfred/MediaStateT

MediaStateT Gitee项目地址: https://gitee.com/MediaState/MediaStateT

2. 效果展示

以前界面:

目前界面:

窗口绘制:

PopWindow使用Loader控件进行了模块化,非常好用,可以随便在Loader里面添加控件

需要注意的是,添加到Loader中的控件id不能被外部所访问,所以建议在外部先加载好控件然后传递到Loader

直接在source_component添加Conponent控件即可

需要注意的是Component只能有一个控件,所以建议先创建一个大的Rectangle然后再在Rectangle里面创建其他控件,最后传递Component也就传递了Rectangle及其整个界面

文章最后有调用示例,可以参考 3. 代码参考

这次只是相较于上次添加了一些组件和虚化效果,还有主函数的调用逻辑都进行了更新。

整体的代码不是很难,必要的注释都写在代码里了。需要注意的是:

PopWindow.qml 的Window属性的x y 可以被外部调用的时候被覆盖. 窗口的大小根据Loader里面content_loader的内容大小改变 sign这个变量只是一个标志,为了防止动画被多次执行。 PopWindow.qml import QtQuick import QtQuick.Controls import QtQuick.Window Window{ id: pop_window visible: true visibility: Window.Windowed color: "transparent" // 透明度 opacity: 0 // 取消边框 flags:Qt.FramelessWindowsHint | Qt.ToolTip // 设置为非模态 modality: Qt.NonModal //设置初始位置(外部设置会覆盖此设置) x: Screen.width - content_loader.width y: 100 //根据Loader设置大小 width: content_loader.width height: content_loader.height MouseArea{ id:content_mouse anchors.fill: parent hoverEnabled: true } // 设置出现后显示时间的计时器 Timer{ id:show_timer interval: 2500 repeat: true onTriggered:{ //这个if实现了鼠标悬停保留窗口的效果 if(!loader_mouse.containsMouse){ hideWindow(); } } } //绘制图形的Loader,供外部使用 property alias source_component:content_loader.sourceComponent Loader{ id:content_loader MouseArea{ id:loader_mouse anchors.fill:parent hoverEnabled:true } } //---------------------------动画部分开始------------------- //设置出现显示动画相对于设置的x值的偏移位置,这里变量外部进行了设置 property int x_offset: 0 property int x_origin: 0 //设置sign标志,防止多次showWindow调用造成多次动画显示 property int sign: 0 ParallelAnimation{ id: show_anim // 透明度动画 PropertyAnimation{ target:pop_window property: "opacity" easing.type: Easing.InQuart from:pop_window.opacity to: 1 duration:350 } // 位置移动动画 PropertyAnimation{ target:pop_window property: "x" easing.type: Easing.OutBounce //从当前值开始移动 from: pop_window.x to: Screen.width - content_loader.width - x_offset duration:800 } // 大小缩放动画 PropertyAnimation{ target:pop_window property: "width" easing.type: Easing.OutCirc //从当前值开始移动 from: 0 to: content_loader.width duration:200 } // 大小缩放动画 PropertyAnimation{ target:pop_window property: "height" easing.type: Easing.OutCirc //从当前值开始移动 from: 0 to: content_loader.height duration:200 } onStarted:{ pop_window.show() } //出现动画结束信号 onFinished:{ show_timer.restart() } } //设置关闭显示动画 ParallelAnimation{ id: hide_anim // 透明度动画 PropertyAnimation{ target:pop_window property: "opacity" easing.type: Easing.OutCubic from:pop_window.opacity to: 0 duration:800 } //位置移动动画 PropertyAnimation{ target:pop_window property: "x" easing.type: Easing.InExpo //从当前值开始移动 from: pop_window.x to: x_origin duration:800 } //大小缩放动画 PropertyAnimation{ target:pop_window property: "width" easing.type: Easing.InQuint //从当前值开始移动 from: content_loader.width + 10 to: 0 duration:1000 } //大小缩放动画 PropertyAnimation{ target:pop_window property: "height" easing.type: Easing.InQuint //从当前值开始移动 from: content_loader.height + 10 to: 0 duration:1000 } //结束动画结束之后停止定时器 onFinished:{ show_timer.stop() } } //显示弹窗 function showWindow(){ if(sign === 0){ hide_anim.stop() show_anim.start() sign = 1 } } //隐藏弹窗 function hideWindow(){ if(sign === 1){ show_anim.stop() hide_anim.start() sign = 0 } } //---------------------------动画部分结束------------------- }

调用:

media_stateT.qml import QtQuick import QtQuick.Controls import QtQuick.Window import Qt5Compat.GraphicalEffects import Qt.labs.platform import qt.txwh.MT_info_get 1.0 Item{ //绘制窗口,然后传到PopWindow模块的Loader里 Component{ id:window_draw Rectangle{ id:bk_rectangle width:200 height:70 radius:10 color: Qt.rgba(0.8,0.8,0.8,0.95) Image{ id:img_background width:bk_rectangle.width - 40 height:bk_rectangle.height - 16 source:"/icon/MtIcon.jpg" smooth: true mipmap:true cache:false visible:false fillMode: Image.PreserveAspectCrop anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter : parent.horizontalCenter anchors.right: parent.right anchors.rightMargin: 6 } Rectangle { id: img_bck_mask width: img_background.width height: img_background.height radius: 10 color: "red" visible: false } OpacityMask { anchors.fill: img_background source: img_background maskSource: img_bck_mask } FastBlur { anchors.fill: img_background source: img_background radius: 32 transparentBorder:true } Image { id: img width: 60 height: 60 anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.leftMargin:6 source: "/icon/MtIcon.jpg" sourceSize.width:1024 sourceSize.height:1024 smooth: true mipmap:true visible: false cache:false } Rectangle { id: img_mask width: img.width height: img.height radius: 10 color: "red" visible: false } OpacityMask { anchors.fill: img source: img maskSource: img_mask } TextScroll{ id:music_name_label width:110 anchors.verticalCenter: parent.verticalCenter anchors.verticalCenterOffset: -16 anchors.left:img.right anchors.leftMargin:10 fontPixelSize:17 text:qsTr("Music Name") } TextScroll{ id:player_name_label width:110 anchors.verticalCenter: parent.verticalCenter anchors.verticalCenterOffset: 16 anchors.left:img.right anchors.leftMargin:10 fontPixelSize:13 text:qsTr("Player") } //获取信息类,这是一个C++类 MT_info_get{ id:mt_info_get //存储上一次的history时间信息,用string是为了防止数字过大造成溢出 property string last_file_time; //这边从C++传来的值进行赋值的时候需要写function() //这里QT6和Qt5的Quick有些不同 //这样子加个function可以很明显的标识这是由emit传来的signal的参数 //详细链接可以参考这个: https://www.direktembedded.com/qt5-to-qt6-qml-pyside-porting/ onNe_file_time_got: function(temp_time){ if(temp_time != last_file_time){ //获取信息 mt_info_get.music_info_get() mt_info_get.player_info_get() mt_info_get.img_download() //显示窗口 pop_window.showWindow() last_file_time = temp_time } } onMusic_info_got: function(music_name){ music_name_label.text = music_name //重新获取图片 mt_info_get.img_download() //由于QtImage存在缓存机制,需要cache:false并且先置空路径再设置路径才会加载图片,不改变路径直接调用上次的缓存 img.source = "" img.source = "file:./album.jpg" img_background.source = "" img_background.source = "file:./album.jpg" } onPlayer_info_got: function(player_name){ player_name_label.text = player_name } onAutostart_status: function(value){ if (value){ menu_right.sws.checked = true }else{ menu_right.sws.checked = false } } onHot_key_activated: function(value){ if(value === 1){ pop_window.showWindow() }else if(value === 2){ mt_fre.showWindow() }else if(value === 3){ mtBoardConnect.init(); menu_right.connectMSBoardState = true; } } onGot_mouse_cursor: //Qt6用法。qt5可忽略function function(x,y,scale){ menu_righnu_x = x / scale menu_righnu_y = y / scale menu_right.show() //展现在最上层 menu_right.raise() } //获取网易云音乐history的修改时间函数 function ne_file_time(){ mt_info_get.NE_file_time() } } // 循环更新网易云歌曲等参数 Timer{ interval:500 repeat:true running:true onTriggered:{ mt_info_get.ne_file_time(); } } SystemTrayIcon{ id:system_icon visible: true icon.source: "qrc:/icon/MtIcon.jpg" tooltip:"MediaStateT" onActivated: //reason是SystemTrayIcon固有属性,不同数值对应不同的按键事件 //来源:https://gist.github.com/kviktor/ function(reason){ //双击,单机,2,3,右键1 if(reason === 2 || reason === 3){ //显示窗口 pop_window.showWindow() }else if(reason === 1){ //定义过的槽函数,执行操作后,然后发射到get_mouse_cursor mt_info_get.get_mouse_cursor() } } } PageMenu{ id:menu_right onSws_click:{ if(menu_right.sws.checked){ mt_info_get.create_sws() // 再次进行状态检测确保添加成功 mt_info_get.check_start_with_system() }else{ mt_info_get.remove_sws() mt_info_get.check_start_with_system() } } Component.onCompleted: mt_info_get.check_start_with_system() onSw_click:{ pop_window.showWindow() } onSf_click:{ mt_fre.showWindow() } } } } PopWindow{ id:pop_window // 设置初始位置,对PopWindow里面的x,y进行了覆盖 x_offset: get_screen_pixel(0.005, Screen.width) x: get_screen_pixel(0.94, Screen.width) //设置0.94不设置1是为了防止不同缩放下屏幕边缘乱跳的问题 y: get_screen_pixel(0.13, Screen.height) x_origin: get_screen_pixel(0.94, Screen.width) source_component:window_draw // 为了适应不同的屏幕,需要使用百分比表示 function get_screen_pixel(percent, sum_pixel){ return percent * sum_pixel } } PageAudioFrequency{ id:mt_fre } }

参考:

QML实现桌面右下角弹窗 PropertyAnimation QML Type


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3