上节我们讲到,我们在修复了ChartView导致程序崩溃的问题之后,又导致了MenuItem托盘右键菜单无法使用的问题。今天我们就来解决这个问题。
教程被应用在MediaStateT中
MediaStateT Github项目地址: https://github.com/taxue-alfred/MediaStateT
MediaStateT Gitee项目地址: https://gitee.com/MediaState/MediaStateT
效果图展示
那既然没法用了。。首先就是Google一下。然后发现可能是官方的BUG??那既然是官方的BUG,那我们就绕开这个BUG换种思路走🤣
解决思路
我们可以直接在托盘检测鼠标按键,如果为右键,那么我们创建一个新窗口,然后顺便可以将这个窗口美化,整的比较好看一些。但是有几个要考虑问题:
- 如何在全局获取到鼠标的位置,然后在当前的鼠标位置创建窗口
- 当窗口打开后,鼠标移开菜单区域之后,窗口怎么实现自动隐藏?
这期我们只是实现如何右键创建窗口,并且对窗口进行美化。
首先当然是创建一个窗口,然后隐藏任务栏和窗口栏,设置大小等。不多赘述
Window{
id:root_window
//便于外部的变量控制
property int menu_x
property int menu_y
x:menu_x
//这里为了让窗口左下角和鼠标对齐(默认左上角)
y:menu_y - height
width: 136
height: 180
flags:Qt.FramelessWindowsHint | Qt.ToolTip
modality: Qt.NonModal
color: "transparent"
}
然后我们创建一些信号(根据自己菜单数目,我这里一共四个控件需要发射信号),表示我们当前鼠标点击过了
//定义信号,发射给调用控件
signal sws_click
signal sw_click
signal sf_click
signal cm_click
接下来就是给窗口填充控件了,这里我就拿一个Rectangle举例,我的项目一共五个,为了避免篇幅过长,拿一个举例,其他类似
//PageMenu.qml
//一个大的背景Rectangle
Rectangle{
radius:8
width:root_window.width
height:root_window.height
Column{
anchors.centerIn: parent
RoundButton{
id: start_with_system
width:root_window.width
height:36
radius:8
checkable:true
background:
Rectangle{
id:sws_bk
radius:8
color: start_with_system.checked ? "whitesmoke" :
(start_with_system.hovered ? "lightgrey" :
"white")
Image{
id:sws_img
anchors.left:parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin:12
smooth:true
width:20
height:20
source:"/icon/start.svg"
}
Text{
anchors.left:sws_img.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin:28
text:"自动启动"
font.pointSize:9
}
}
//发送信号(上面定义过)
onClicked:root_window.sws_click()
}
}
}
接下来就是要在另一个文件里面来实现右键唤出这个窗口。全项目请看:
MediaState软件项目地址:https://gitee.com/txwh-media-state
//media_state_T.qml
SystemTrayIcon{
id:system_icon
visible: true
icon.source: "qrc:/album.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()
}
}
}
下面的代码可能会看不懂,这里解释一下。获取鼠标的坐标需要在C++调用GetDesktopWindow
这个WindowAPI,然后发送信号到QML。信号名称为get_mouse_cursor
, scale
为缩放率,为了适配高分屏。后面的文章会讲到
//media_state_T.qml(主QML)
onGot_mouse_cursor:
//Qt6用法。qt5可忽略function
function(x,y,scale){
menu_right.menu_x = x / scale
menu_right.menu_y = y / scale
menu_right.show()
//展现在最上层
menu_right.raise()
}
来看看效果:
其他的上下节的文章看我的这个Qt收录吧,。。实在是懒得写上下节了。