将应用程序从Qt / C ++移动到Qt / QML时,遇到系统托盘的问题。目的是将系统托盘的C ++代码部分的或全部的转换为QML代码。我意识到,第一个选项是利用信号和插槽机制包装QSystemTrayIcon,QMenu。这个解决方案非常符合逻辑,因为QML不是一个工具,比如使用MenuBar来构建System Tray。所以我们做了一个包装器,它可以在QML层中与QSystemTrayIcon进行交互。
在包装器实现之后,我注意QML不仅可以访问信号和插槽,还可以访问Q_PROPERTY的参数。也就是说,在QSystemTrayIcon类中,实际上只能将此类注册为QML中的类型层,并尝试在QML上编写几乎所有代码。
因此,在本文中,您将看到两个在QML中实现系统托盘的方法
通过单击系统托盘中的图标以及按关闭按钮,最终应用程序将最小化到系统托盘。但只有在活动时才会激活特殊复选框以控制应用程序窗口向系统托盘的折叠过程,如果未启用该复选框,则应用程序将关闭。此外,可以使用系统托盘图标中的活动复选框菜单项关闭应用程序。
Variant通过包装类使用系统托盘。
这个项目包含以下文件:
QmlSystemTray.pro - 你知道这是啥
main.cpp -启动应用的主要文件
systemtray.h
systemtray.cpp -QSystemTrayIcon的包装
main.qml - QML代码
logo-min.png
TEMPLATE = app
QT += qml quick widgets
SOURCES += main.cpp \
systemtray.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
HEADERS += \
systemtray.h
对单独的Qt / C ++类的对象进行声明和初始化,并从Qml层设置对它的访问。
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QSystemTrayIcon>
#include <systemtray.h>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
SystemTray * systemTray = new SystemTray();
QQmlContext * context = engine.rootContext();
// 将systemTray放入QML上下文中
context->setContextProperty("systemTray", systemTray);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
头文件声明了将信息传递给QML的SystemTray类的信号,以及将要进行交互的QSystemTrayIcon对象。 另外,我们声明与此图标交互的处理程序。
#ifndef SYSTEMTRAY_H
#define SYSTEMTRAY_H
#include <QObject>
#include <QAction>
#include <QSystemTrayIcon>
class SystemTray : public QObject
{
Q_OBJECT
public:
explicit SystemTray(QObject *parent = 0);
signals:
void signalIconActivated();
void signalShow();
void signalQuit();
private slots:
/* 将接受来自点击系统托盘中的应用程序图标的事件的槽
*/
void iconActivated(QSystemTrayIcon::ActivationReason reason);
public slots:
void hideIconTray();
private:
/* Declare the object of future applications for the tray icon*/
QSystemTrayIcon * trayIcon;
};
#endif // SYSTEMTRAY_H
接下来,我们编写该类的源代码以使用系统托盘,但在与菜单项和系统托盘图标的交互中仅实现供应信号。 信号处理逻辑以QML实现。
#include "systemtray.h"
#include <QMenu>
#include <QSystemTrayIcon>
SystemTray::SystemTray(QObject *parent) : QObject(parent)
{
// 创建两个项目的QMenu
QMenu *trayIconMenu = new QMenu();
QAction * viewWindow = new QAction(trUtf8("Развернуть окно"), this);
QAction * quitAction = new QAction(trUtf8("Выход"), this);
/* 将单击信号连接至适当的QML信号中
* */
connect(viewWindow, &QAction::triggered, this, &SystemTray::signalShow);
connect(quitAction, &QAction::triggered, this, &SystemTray::signalQuit);
trayIconMenu->addAction(viewWindow);
trayIconMenu->addAction(quitAction);
/* Initialize the tray icon, icon set, and specify the tooltip
* */
trayIcon = new QSystemTrayIcon();
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon(":/logo-min.png"));
trayIcon->show();
trayIcon->setToolTip("Tray Program" "\n"
"Work with winimizing program to tray");
/* 连接点击在托盘图标上的信号
* */
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
}
/* 点击托盘图标的事件处理
* */
void SystemTray::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason){
case QSystemTrayIcon::Trigger:
// In the case of pressing the signal on the icon tray in the call signal QML layer
emit signalIconActivated();
break;
default:
break;
}
}
void SystemTray::hideIconTray()
{
trayIcon->hide();
}
要访问Qml层中SystemTray类的对象的属性,请指定对象Connections,通过该对象连接到SystemTray对象。 制定目标属性名称是在main.cpp文件中进行的的,当安装引擎时,通过系统托盘setContextProperty()方法访问对象的Qml。
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Window 2.0
ApplicationWindow {
id: application
visible: true
width: 640
height: 480
title: qsTr("Hello World")
// Chance to ignore the checkbox
property bool ignoreCheck: false
/* 将systemTray的信号连接至本地
* */
Connections {
target: systemTray
// 这些都是上面我们定义的systemTray的信号
onSignalShow: {
application.show();
}
// The signal - close the application by ignoring the check-box
onSignalQuit: {
ignoreCheck = true
close();
}
// 通过点击系统托盘图标显示隐藏窗口
onSignalIconActivated: {
if(application.visibility === Window.Hidden) {
application.show()
} else {
application.hide()
}
}
}
// 控制关闭窗口的CheckBox
CheckBox {
id: checkTray
anchors.centerIn: parent
text: qsTr("关闭窗口时,最小化至系统托盘")
}
//处理窗口关闭
onClosing: {
if(checkTray.checked === true && ignoreCheck === false){
close.accepted = false
application.hide()
} else {
Qt.quit()
}
}
}
在这个版本中,包含以下文件
在这种情况下,我建议您注意项目中连接的模块。 因为没有quickwidgets模块不起作用。
TEMPLATE = app
QT += qml quick widgets quickwidgets
SOURCES += main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
还需要将库连接到QQuickWidget main.cpp源文件。 有必要使用qmlRegisterType函数。
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QIcon>
#include <QQuickWidget>
#include <QSystemTrayIcon>
#include <QQmlContext>
// Declare a user-defined data type to work with an icon in QML
Q_DECLARE_METATYPE(QSystemTrayIcon::ActivationReason)
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
// Register QSystemTrayIcon in Qml
qmlRegisterType<QSystemTrayIcon>("QSystemTrayIcon", 1, 0, "QSystemTrayIcon");
// Register in QML the data type of click by tray icon
qRegisterMetaType<QSystemTrayIcon::ActivationReason>("ActivationReason");
// Set icon in the context of the engine
engine.rootContext()->setContextProperty("iconTray", QIcon(":/logo-min.png"));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
接下来,我们声明QSystemTrayIcon对象并在onCompleted方法中对其进行配置。 由于我们已经注册了类型QSystemTrayIcon :: ActivationReason,因此根据发送的值的类型,我们能够使用onActivated方法来确定对系统托盘中的应用程序图标的鼠标点击的响应。 当我们右键单击系统托盘中的应用程序图标时,会出现一个菜单。 菜单是一个函数popup()。 功能特征是它在鼠标光标所在的位置调出菜单,因此菜单出现在系统托盘图标的位置。
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Window 2.0
import QSystemTrayIcon 1.0
ApplicationWindow {
id: application
visible: true
width: 640
height: 480
title: qsTr("Hello World")
// Registered in the system tray QML layer
QSystemTrayIcon {
id: systemTray
// Initial initialization of the system tray
Component.onCompleted: {
icon = iconTray // Set icon
toolTip = "Tray Program"
show();
}
/* 鼠标在托盘上左击或者右击分别处理不同的相应
* 1是QSystemTrayIcon::Context
* */
onActivated: {
if(reason === 1){
trayMenu.popup()
} else {
if(application.visibility === Window.Hidden) {
application.show()
} else {
application.hide()
}
}
}
}
// Menu system tray
Menu {
id: trayMenu
MenuItem {
text: qsTr("Maximize window")
onTriggered: application.show()
}
MenuItem {
text: qsTr("Exit")
onTriggered: {
systemTray.hide()
Qt.quit()
}
}
}
// Test check box to control the closing of the window
CheckBox {
id: checkTray
anchors.centerIn: parent
text: qsTr("Enable minimizing to system tray during the closing the window")
}
onClosing: {
/* If the check box should not be ignored and it is active, then hide the application.
* Otherwise, close the application
* */
if(checkTray.checked === true){
close.accepted = false
application.hide()
} else {
Qt.quit()
}
}
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章