能否在Qt Quick应用程序中实现SystemTrayIcon功能?

6
我正在编写一个QtQuick桌面应用程序。其中包括c++(用于功能)和QML(用于UI)。 我使用QQuickView来显示用QML编写的界面。
我希望在最小化时将此应用程序放置在系统托盘中。
我的意思是类似于这个例子的功能。http://qt-project.org/doc/qt-4.8/desktop-systray.html。 我正在尝试实现此功能,但无法找到在我的Qt Quick应用程序中实现此功能的方法。
这是我的main.cpp代码:
#include <QGuiApplication>
#include <QQmlEngine>
#include <QQmlContext>
#include <QQmlFileSelector>
#include <QQuickView>
#include "myapp.h"

int main(int argc, char* argv[])
{
    QGuiApplication app(argc,argv);
    app.setApplicationName(QFileInfo(app.applicationFilePath()).baseName());
    QDir::setCurrent(qApp->applicationDirPath());

    MyApp myappObject;

    QQuickView view;

    view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));
    view.rootContext()->setContextProperty("myappObject", &myappObject);
    new QQmlFileSelector(view.engine(), &view);

    view.setSource(QUrl("qrc:///myapp.qml"));

    view.setResizeMode(QQuickView::SizeRootObjectToView);   
    view.show();

    return app.exec();
}

请提供任何提示/指针以完成此操作。
谢谢。

你是打算只使用QML来完成这个吗?还是可以使用C++/Qt? - BlueMagma
嗨,BlueMagma,您可以使用C++/Qt。我的用户界面是使用QML创建的,并且我从Qt main.cpp文件中启动它。我刚刚在我的问题中更新了main.cpp文件的代码。 - Mugunth
2个回答

14

今天我也面临同样的挑战,在main()函数中使用了下面的解决方案。在使用Qt 5.3时效果很好。当然,你应该实现更好的方式来检查第一个根对象是否是你的应用程序窗口对象。

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QMessageBox>
#include <QAction>
#include <QMenu>
#include <QSystemTrayIcon>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    if (!QSystemTrayIcon::isSystemTrayAvailable()) {
        QMessageBox::critical(0, QObject::tr("Systray"),
                                 QObject::tr("I couldn't detect any system tray "
                                             "on this system."));
        return 1;
    }
    QApplication::setQuitOnLastWindowClosed(false);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    QObject *root = 0;
    if (engine.rootObjects().size() > 0)
    {
        root = engine.rootObjects().at(0);

        QAction *minimizeAction = new QAction(QObject::tr("Mi&nimize"), root);
        root->connect(minimizeAction, SIGNAL(triggered()), root, SLOT(hide()));
        QAction *maximizeAction = new QAction(QObject::tr("Ma&ximize"), root);
        root->connect(maximizeAction, SIGNAL(triggered()), root, SLOT(showMaximized()));
        QAction *restoreAction = new QAction(QObject::tr("&Restore"), root);
        root->connect(restoreAction, SIGNAL(triggered()), root, SLOT(showNormal()));
        QAction *quitAction = new QAction(QObject::tr("&Quit"), root);
        root->connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));

        QMenu *trayIconMenu = new QMenu();
        trayIconMenu->addAction(minimizeAction);
        trayIconMenu->addAction(maximizeAction);
        trayIconMenu->addAction(restoreAction);
        trayIconMenu->addSeparator();
        trayIconMenu->addAction(quitAction);

        QSystemTrayIcon *trayIcon = new QSystemTrayIcon(root);
        trayIcon->setContextMenu(trayIconMenu);
        trayIcon->setIcon(QIcon(":/resources/DatagnanLogoColor.png"));
        trayIcon->show();
    }

    return app.exec();
}

缺点:它导致Qt5Widgets模块依赖。似乎不可能从纯QML中使用系统托盘。 - Dmitry Sazonov

-2
将 systray 示例中的 Windos 类(window.cpp/window.h)复制到你的项目中,如果必要的话将其移植到 Qt5,并在你的主文件中打开两个文件:
int main(int argc, char* argv[])
{
    // ...
    QQuickView view;
    // ... 
    view.show();

    Window window;
    window.show();

    return app.exec();
}

嗨,Sion Wart,我在哪里可以获取window.cpp和window.h文件? - Mugunth
我理解你所说的是来自 systray 示例的 windows.cpp / windows.h 文件。我尝试了它们,并使其工作。但是,无论是由 Window.cpp 发起的 Windows 窗口还是通过 QML(通过 QQuickView)创建的基于 QML 的窗口都会出现。这并不能满足我的需求。如何将它们集成在一起。如果可能,请提供更多细节。 - Mugunth
现在您需要在C++中集成您的功能。根据您的需求修改“Window”类,并开始在主程序和“Window”之间发送信号,例如显示/隐藏/修改图标。 - Simon Warta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接