[Qt6][QML][教程]自定义一个漂亮的托盘右键菜单

上节我们讲到,我们在修复了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收录吧,。。实在是懒得写上下节了。

https://blog.csdn.net/qq_38844263/category_11578713.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值