Qt开发 — 在QML中使用系统托盘

29 篇文章 10 订阅
24 篇文章 3 订阅

Qt开发 — 在QML中使用系统托盘

简介:在Qt创建App 托盘在QT5.8之后引入了 Qt Labs Platform模块。因此QT5.8之后可以分为两种中途径实现:

1、SystemTrayIcon

系统提供的接口,实现比较简单。但是需要引入Qt Labs Platform 会和某一些实用的空间样事儿有冲突,自行决定取舍。不做简述。

2、QSystemTrayIcon

在qml中使用QSystemTrayIcon的方法,也可以作为qml与c++交互的例子来看:

JHSystemTray.qml
import QtQuick 2.6
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
import Tiertime.utility 1.0



SystemTrayIcon{
	id: systemTray
	menu: menu
	visible: true
	icon: "qrc:///ico/wand.ico"
	toolTip: "Wand is runing"
	onTrigger:{
		mainWnd.requestActivate();
		mainWnd.show();
		mainWnd.raise();
	}



	MyMenu{
		id: menu
		MyAction{
			text: "Search printer"
			onTriggered: {
			}
		}

		MySeparator {}

		MyAction{
			id:exitItem
			text: "Exit"
			onTriggered: Qt.quit()
		}
	}
}



效果和widget下使用是一样的,但用qml更简单更方便。

自定义的SystemTrayIcon我注册到XX.utility 1.0中。下面讲解其实现。

systemtrayicon.h
#ifndef SYSTEMTRAYICON_H
#define SYSTEMTRAYICON_H
 
#include <QAction>
#include <QQuickItem>
#include <QSystemTrayIcon>
 
class MyAction : public QAction
{
    Q_OBJECT
    Q_PROPERTY(QUrl icon READ icon WRITE setIcon NOTIFY iconChanged)    //Q_PROPERTY宏提供在qml中访问的信号槽等等
 
public:
    MyAction(QObject *parent = nullptr);
    ~MyAction();
 
    QUrl icon() const;
 
signals:
    void iconChanged();
 
public slots:
    void setIcon(const QUrl &arg);
 
private:
    QUrl m_icon;
};
 
 
class MySeparator : public QObject
{
public:
    MySeparator(QObject *parent = nullptr);
    ~MySeparator();
};
 
class SystemTray;
class MyMenu : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
    Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
 
public:
    MyMenu(QQuickItem *parent = nullptr);
    ~MyMenu();
 
    int width() const;
    int height() const;
    void clear();
 
signals:
    void widthChanged();
    void heightChanged();
 
public slots:
    void setWidth(int arg);
    void setHeight(int arg);
    void addSeparator();
    void addAction(MyAction *action);
    void addMenu(MyMenu *menu);
 
protected:
    void componentComplete();
 
private:
    friend class SystemTrayIcon;    //让SystemTray能够直接访问m_menu
    QMenu *m_menu;
};
 
class SystemTrayIcon : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(int x READ x CONSTANT)
    Q_PROPERTY(int y READ y CONSTANT)
    Q_PROPERTY(QUrl icon READ icon WRITE setIcon NOTIFY iconChanged)
    Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY toolTipChanged)
    Q_PROPERTY(MyMenu* menu READ menu WRITE setMenu NOTIFY menuChanged)
 
public:
    SystemTrayIcon(QQuickItem *parent = nullptr);
    ~SystemTrayIcon();
 
    int x() const;
    int y() const;
    QUrl icon() const;
    QString toolTip() const;
    MyMenu* menu() const;
 
signals:
    void trigger();
    void iconChanged();
    void toolTipChanged();
    void menuChanged();
 
public slots:
    void setIcon(const QUrl &arg);
    void setToolTip(const QString &arg);
    void setMenu(MyMenu *arg);
    void onVisibleChanged();
    void onActivated(QSystemTrayIcon::ActivationReason reason);
    void onExit();
 
private:
    QSystemTrayIcon *m_systemTray;
    MyMenu *m_menu;
    QString m_toolTip;
    QUrl m_icon;
};
 
#endif // SYSTEMTRAYICON_H

要将c++类导入到qml必须继承自QObject或其派生类,并使用Q_OBJECT宏。

而继承QQuickItem是为了得到item中的其他一些属性和信号,以及重实现 void componentComplete()。

该函数在组件完成时调用,重新实现来添加必要的操作。

systemTrayIcon.cpp
#include <QApplication>
#include <QMenu>
#include <QAction>
#include "systemtrayicon.h"
 
MyAction::MyAction(QObject *parent)
    :   QAction(parent)
{
    setObjectName("MyAction");
}
 
MyAction::~MyAction()
{
 
}
 
QUrl MyAction::icon() const
{
    return m_icon;
}
 
void MyAction::setIcon(const QUrl &arg)
{
    if(m_icon != arg)
    {
        QString str = arg.toLocalFile();
        if(str == "") str = arg.toString();     //如果转换失败
        if( str.mid (0, 3) == "qrc")
            str = str.mid (3, str.count() - 3);
        QAction::setIcon(QIcon(str));
        m_icon = arg;
        emit iconChanged();
    }
}
 
MySeparator::MySeparator(QObject *parent)
    :   QObject(parent)
{
    setObjectName("MySeparator");
}
 
MySeparator::~MySeparator()
{
 
}
 
MyMenu::MyMenu(QQuickItem *parent)
    :   QQuickItem(parent)
{
    setObjectName("MyMenu");
    m_menu = new QMenu();
}
 
MyMenu::~MyMenu()
{
 
}
 
int MyMenu::width() const
{
    return m_menu->width();
}
 
int MyMenu::height() const
{
    return m_menu->height();
}
 
void MyMenu::clear()    //清空caidan
{
    m_menu->clear();
}
 
void MyMenu::setWidth(int arg)
{
    if (m_menu->width() != arg)
    {
        m_menu->setFixedWidth(arg);
        emit widthChanged();
    }
}
 
void MyMenu::setHeight(int arg)
{
    if (m_menu->height() != arg)
    {
        m_menu->setFixedHeight(arg);
        emit heightChanged();
    }
}
 
void MyMenu::addAction(MyAction *action)
{
    m_menu->addAction(action);
}
 
void MyMenu::addSeparator()
{
    m_menu->addSeparator();
}
 
void MyMenu::addMenu(MyMenu *menu)
{
    m_menu->addMenu(menu->m_menu);
}
 
void MyMenu::componentComplete()        //在菜单完成构建后调用,将自定义Action,Menu,Separator通过objectName判断加入
{
    QQuickItem::componentComplete();
    QObjectList list = children();
    for (auto it : list)
    {
        if (it->objectName() == "MyAction")
        {
            MyAction *action = qobject_cast<MyAction *>(it);
            m_menu->addAction(action);
        }
        else if (it->objectName() == "MySeparator")
        {
            m_menu->addSeparator();
        }
        else if (it->objectName() == "MyMenu")
        {
            MyMenu *menu = qobject_cast<MyMenu *>(it);
            m_menu->addMenu(menu->m_menu);
        }
    }
}
 
SystemTrayIcon::SystemTrayIcon(QQuickItem *parent)
    :   QQuickItem(parent)
{
    m_systemTray = new QSystemTrayIcon(this);
    connect(m_systemTray, &QSystemTrayIcon::activated, this, &SystemTrayIcon::onActivated);
    connect(this, &SystemTrayIcon::visibleChanged, this, &SystemTrayIcon::onVisibleChanged);
    setVisible(false);              //给visible一个初始值,否则会不显示
}
 
SystemTrayIcon::~SystemTrayIcon()
{
 
}
 
int SystemTrayIcon::x() const
{
    return m_systemTray->geometry().x();
}
 
int SystemTrayIcon::y() const
{
    return m_systemTray->geometry().y();
}
 
QUrl SystemTrayIcon::icon() const
{
    return m_icon;
}
 
QString SystemTrayIcon::toolTip() const
{
    return m_systemTray->toolTip();
}
 
MyMenu *SystemTrayIcon::menu() const
{
    return m_menu;
}
 
void SystemTrayIcon::setIcon(const QUrl &arg)
{
    if(m_icon != arg)
    {
        QString str = arg.toLocalFile();
        if(str == "") str = arg.toString(); //如果转换失败
        if( str.mid (0, 3) == "qrc")
            str = str.mid (3, str.count() - 3);
        m_systemTray->setIcon(QIcon(str));
        m_icon = arg;
        emit iconChanged();
    }
}
 
void SystemTrayIcon::setToolTip(const QString &arg)
{
    if (m_toolTip != arg)
    {
        m_systemTray->setToolTip(arg);
        m_toolTip = arg;
        emit toolTipChanged();
    }
}
 
void SystemTrayIcon::setMenu(MyMenu *arg)    //设置托盘上下文菜单
{
    if (m_menu != arg)
    {
        m_menu = arg;
        m_systemTray->setContextMenu(m_menu->m_menu);
        m_systemTray->installEventFilter(this);
        emit menuChanged();
    }
}
 
void SystemTrayIcon::onVisibleChanged()    //visible可见性改变时显示/隐藏托盘
{
    m_systemTray->setVisible(isVisible());
}
 
void SystemTrayIcon::onActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason)
    {
    case QSystemTrayIcon::DoubleClick:
    case QSystemTrayIcon::Trigger:
        emit trigger();            //单击双击托盘图标时发送trigger()信号, reason类似还有Context,MiddleClick,Unknow
 
    default:
        break;
    }
}
 
void SystemTrayIcon::onExit()    //应在程序退出时调用,防止图标不消失
{
    m_systemTray->hide();
    QApplication::exit(0);
}

main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "systemtrayicon.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);
 
    QQmlApplicationEngine engine;
    qmlRegisterType<MyMenu>("xx.utility", 1, 0, "MyMenu");        //注册到qml中
    qmlRegisterType<MyAction>("xx.utility", 1, 0, "MyAction");
    qmlRegisterType<MySeparator>("xx.utility", 1, 0, "MySeparator");
    qmlRegisterType<SystemTrayIcon>("xx.utility", 1, 0, "SystemTrayIcon");
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
 
    return app.exec();
}

资源下载路径: systemtrayicon

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值