最近看到MAC上的网易云音乐播放音乐切换歌曲的时候会有一个弹窗,个人感觉这功能挺不错的,但是Windows却没有这个功能,所以就想着去实现一下,正好加一些功能,再和单片机做配合做成一整个体系算了。
教程被应用在MediaStateT中
MediaStateT Github项目地址: https://github.com/taxue-alfred/MediaStateT
MediaStateT Gitee项目地址: https://gitee.com/MediaState/MediaStateT
效果展示
窗口调用:
PopWindow
使用Loader
控件进行了模块化,非常好用,可以随便在Loader里面添加控件
需要注意的是,添加到Loader中的控件id不能被外部所访问,所以建议在外部先加载好控件然后传递到Loader
- 直接在
source_component
添加Conponent
控件即可
需要注意的是Component只能有一个控件,所以建议先创建一个大的Rectangle然后再在Rectangle里面创建其他控件,最后传递Component也就传递了Rectangle及其整个界面
- 文章最后有调用示例,可以参考
代码参考
整体的代码不是很难,必要的注释都写在代码里了。需要注意的是:
PopWindow.qml
的Window
属性的x
y
可以被外部调用的时候被覆盖.- 窗口的大小根据
Loader
里面content_loader
的内容大小改变 sign
这个变量只是一个标志,为了防止动画被多次执行。
//PopWindow.qml
import QtQuick
import QtQuick.Controls 2.5
import QtQuick.Window 2.3
Window{
id: pop_window
visible: false
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
}
}
//---------------------------动画部分开始-------------------
//设置出现显示动画
property int x_offset: 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: Screen.width
to: pop_window.x - content_loader.width - x_offset
duration:800
}
onStarted:{
pop_window.show()
}
//出现动画结束信号
onFinished:{
show_timer.start()
}
}
//设置关闭显示动画
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: Screen.width
duration:800
}
//结束动画结束之后隐藏窗口
onFinished:{
show_timer.stop();
pop_window.hide();
}
}
//显示弹窗
function showWindow(){
if(sign === 0){
show_anim.start()
sign = 1
}
}
//隐藏弹窗
function hideWindow(){
if(sign === 1){
show_anim.stop()
hide_anim.start()
sign = 0
}
}
//---------------------------动画部分结束-------------------
}
调用:
//main.qml
import QtQuick
import QtQuick.Controls 2.5
import QtQuick.Window 2.3
import Qt5Compat.GraphicalEffects
Item{
Timer{
interval:500
repeat:false
running:true
onTriggered:{
pop.showWindow();
}
}
PopWindow{
id:pop
// 设置初始位置,对PopWindow里面的x,y进行了覆盖
x: get_screen_pixel(1, Screen.width)
y: get_screen_pixel(0.13, Screen.height)
x_offset: get_screen_pixel(0.005, Screen.width)
source_component:
Component{
id:test_component
Rectangle{
id:bk_rectangle
width:200
height:70
radius:10
color: Qt.rgba(0.8,0.8,0.8,0.8)
Image {
id: img
width: 60
height: 60
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin:6
source: "/album.jpg"
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
}
Text{
id:music_name_label
width:110
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -16
anchors.left:img.right
anchors.leftMargin:10
font.pixelSize: 17
text:qsTr("Music Name")
}
Text{
id:player_name_label
width:110
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 16
anchors.left:img.right
anchors.leftMargin:10
font.pixelSize: 14
text:qsTr("Player")
}
}
}
// 为了适应不同的屏幕,需要使用百分比表示
function get_screen_pixel(percent, sum_pixel){
return percent * sum_pixel
}
}
}
参考: