qml自定义托盘图标菜单

背景

qt5.15.2自带的MenuItem设置图标,不生效(坑爹)

实现

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import Qt.labs.platform 1.1

Window {
    id: root
    width: 640
    height: 480
    minimumWidth: 640
    maximumWidth: 640
    minimumHeight: 480
    maximumHeight: 480
    visible: true
    title: qsTr("TrayDemo")

    property var menuTray: null
    flags: Qt.FramelessWindowsHint | Qt.Window | Qt.CustomizeWindowHint | Qt.WindowMinimizeButtonHint
    SystemTrayIcon {
        id: trayApp
        icon.source: "qrc:/tray.ico"
        visible: true
        tooltip: "TrayMenu"
        onActivated: {
            if(SystemTrayIcon.Trigger == reason)
                raiseWindow()
            else if(SystemTrayIcon.Context == reason) {
                if(null == menuTray) {
                    var component = Qt.createComponent("qrc:/TrayMenu.qml");
                    if(component.status == Component.Ready) {
                        menuTray = component.createObject(null)
                    }
                }

                var jsonPos = qmlHelper.getMousePos()
                menuTray.x = jsonPos.x
                menuTray.y = jsonPos.y - menuTray.height - 10
                menuTray.showMenu()
            }
        }
    }

    function raiseWindow() {
        root.visible = true
        root.raise()
        root.requestActivate()
    }
}

TrayMenu.qml

import QtQuick.Window 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15


Window {
    id: root
    height: 125
    width: 180
    minimumWidth: 180
    maximumWidth: 180
    minimumHeight: 125
    maximumHeight: 125
    property int radiusWnd: 8
    property int marginSpace: 5
    property int marginWnd: 10
    property int heightItem: 32
    signal trayMenuClick(var nType)
    enum TrayMenuType
    {
        ShowWindow,
        About,
        Exit
    }
    visible: false
    color: "white"
    //flags: Qt.FramelessWindowsHint | Qt.Tool | Qt.CustomizeWindowHint | Qt.WindowMinimizeButtonHint
    flags: Qt.FramelessWindowsHint | Qt.Tool | Qt.CustomizeWindowHint | Qt.WindowMinimizeButtonHint
    Rectangle{
        id:base
        z: 1
        radius: root.radiusWnd
        //antialiasing:true
        anchors.fill: parent
        clip: true
        color: "transparent"
        //color: "#00000000"
        layer.enabled: true
        layer.effect: OpacityMask
        {
            maskSource: Rectangle {
                width: base.width
                height: base.height
                radius: base.radius
            }
        }
        Rectangle{
            radius: radiusWnd
            anchors {
                left: parent.left
                leftMargin: 0
                right: parent.right
                rightMargin: 0
                top: parent.top
                bottom: parent.bottom
            }
            ListView {
                id: viewContent
                model: modelContent
                delegate: delegateContent
                clip: true
                contentWidth: parent.width

                anchors {
                    left: parent.left
                    leftMargin: 0
                    right: parent.right
                    rightMargin: 0
                    top: parent.top
                    topMargin: 0
                    bottom: parent.bottom
                    bottomMargin: marginWnd
                }
            }
            // model for content
            ListModel {
                id: modelContent
            }
            // delegate for content
            Component {
                id: delegateContent
                Rectangle {
                    width: root.width
                    height: heightItem
                    Image {
                        id: imgIcon
                        source: strIcon
                        width: 16
                        height: 16
                        anchors {
                            left: parent.left
                            leftMargin: 10
                            verticalCenter: parent.verticalCenter
                        }
                    }

                    Text {
                        id: textData
                        text: textMenu
                        anchors {
                            left: imgIcon.right
                            leftMargin: 5
                            right: parent.right
                            verticalCenter: parent.verticalCenter
                        }
                        color: "#3B3B3B"
                        font.pointSize: 8
                    }
                    MouseArea {
                        anchors.fill: parent
                        cursorShape: Qt.PointingHandCursor
                        hoverEnabled: true
                        onEntered: {
                            parent.color = "lightblue"//"#F2F2F2"
                        }
                        onExited: {
                            parent.color = "white"
                        }
                        onClicked: {
                            trayMenuClick(type)
                            hideWindow()
                        }
                    }
                }
            }
        }

    }

    Connections {
        target: eventFilter
        function onFocusOut() {
            if(!root.visible) return
            console.log("Focus out..")
            var jsonPos = qmlHelper.getMousePos()
            var x = jsonPos.x
            var y =jsonPos.y
            if((x < root.x || x > root.x + root.height)
               || (y < root.y || y > root.y + root.height)) {
                //console.log("Hide window, x: " + x + ", rootX: " + root.x + ", y: " + y + ", rootY: " + root.y + ", visible: " + root.visible)
                hideWindow()
            }
        }
    }

    function showMenu()
    {
        modelContent.clear()
        modelContent.append({type: TrayMenu.ShowWindow, strIcon: "",textMenu: "显示主窗口"})
        modelContent.append({type: TrayMenu.About, strIcon: "qrc:/tray.ico", textMenu: "关于"})
        modelContent.append({type: TrayMenu.Exit, strIcon: "qrc:/tray.ico", textMenu: "退出"})
        var currentFlags = root.flags
        root.flags = currentFlags | Qt.WindowStaysOnTopHint
        root.requestActivate()
        root.show()
    }

    function hideWindow() {
        var currentFlags = root.flags
        root.flags = currentFlags & ~Qt.WindowStaysOnTopHint
        root.visible = false
        root.hide()
    }
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "QmlHelper.h"
#include "CustomObject.h"

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QCoreApplication::setAttribute(Qt::AA_Use96Dpi);
    QGuiApplication app(argc, argv);
    app.installEventFilter(&EVENT_FILTER_INST);
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("qmlHelper", &QML_CTRL_INST);
    engine.rootContext()->setContextProperty("eventFilter", &EVENT_FILTER_INST);
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreated,
        &app,
        [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        },
        Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

鼠标坐标获取

QVariant QmlHelper::getMousePos()
{
    QPoint screen_pos = QCursor::pos();
    QJsonObject jsonObj;
    jsonObj.insert("x", screen_pos.x());
    jsonObj.insert("y", screen_pos.y());

    return jsonObj;
}

存在问题

1、无边框顶部会有点间距
2、弹出的菜单,首次无法点击外部关闭(需要点击主窗口或点击菜单);再次弹出就不会出现此问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值