Evgenii Legotckoi
Evgenii Legotckoi1. November 2015 12:39

QML - Lektion 008. Arbeiten mit der Taskleiste (QSystemTrayIcon)

Beim Übersetzen der Anwendungsoberfläche von Qt/C++ nach Qt/QML gerieten meine Hände an das Anwendungssymbol in der Taskleiste. Die Aufgabe bestand darin, das Icon im System Tray von C++ nach Qml teilweise oder komplett zu übertragen. Die erste Option, die ich implementiert habe, war ein Wrapper um QSystemTrayIcon mit QMenu unter Verwendung von signal and slot system . Die Lösung ist ziemlich logisch, da es in QML kein vorgefertigtes Objekt wie MenuBar für System Tray gibt. Daher erstellen wir einen Wrapper, mit dem aus der QML -Schicht interagiert werden kann.

Nachdem der Wrapper implementiert war, hatte ich Gelegenheit, mich mit einem Programmierer von Wargamming Konstantin Lyashkevich zu beraten, der mir empfahl, auch auf die Tatsache, dass * QML nicht nur auf Signale und Slots zugreifen kann, sondern auch auf die Parameter Q_PROPERTY , die ebenfalls in der Klasse QSystemTrayIcon enthalten waren, war eigentlich nur möglich diese Klasse als Typ in der QML -Schicht zu registrieren und zu versuchen, fast den gesamten Code in QML zu schreiben. Ich habe diesen Ratschlag getestet und Konstantin das Ergebnis mitgeteilt. Infolgedessen interessierte er sich selbst für diese Aufgabe und wir verbrachten die Abendstunde mit unterhaltsamer Kalkulation und stopften in gemeinsamer Anstrengung QSystemTrayIcon so viel wie möglich in QML. *

Daher sehen Sie in diesem Artikel zwei Implementierungen für die Arbeit mit dem Taskleistensymbol.

Die resultierende Anwendung wird durch Klicken auf das Taskleistensymbol sowie durch Drücken der Schaltfläche zum Schließen des Fensters auf System Tray minimiert. Aber nur wenn ein spezielles Kontrollkästchen aktiv ist, um den Vorgang des Minimierens des Anwendungsfensters in den Tray zu steuern, wird die Anwendung geschlossen, wenn das Kontrollkästchen nicht aktiv ist. Die Anwendung kann auch geschlossen werden, wenn das Kontrollkästchen über den Menüpunkt im Taskleistensymbol aktiv ist.


Erste Wahl

Eine Option zum Arbeiten mit der Taskleiste über eine Wrapper-Klasse.

Projektstruktur für die Arbeit mit System Tray

Das Projekt enthält die folgenden Dateien:

  • QmlSystemTray.pro - Projektprofil;
  • main.cpp - Hauptquellcodedatei zum Ausführen der Anwendung;
  • systemtray.h - Klassen-Header-Datei für die Arbeit mit dem Systemtray;
  • systemtray.cpp - Klassenquellcodedatei für die Arbeit mit dem Systemtray;
  • main.qml - Datei mit dem Hauptanwendungsfenster;
  • logo-min.png - jedes Symbol, das in der Taskleiste platziert wird.

QmlSystemTray.pro

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

main.cpp

Wie in der Lektion über Signale und Slots deklarieren und initialisieren wir ein Objekt einer separaten Qt / C++ -Klasse und setzen den Zugriff darauf von der Qml. -Schicht

#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();
    // Устанавливаем доступ к свойствам объекта класса в контексте QML
    context->setContextProperty("systemTray", systemTray);

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

    return app.exec();
}

systemtray.h

In der Header-Datei der SystemTray -Klasse deklarieren wir die Signale, die Informationen an QML übergeben, sowie das QSystemTrayIcon -Objekt, mit dem die Interaktion durchgeführt wird. Außerdem deklarieren wir mit diesem Icon einen Interaktionshandler.

#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:
    /* Объявляем объект будущей иконки приложения для трея */
    QSystemTrayIcon         * trayIcon;
};

#endif // SYSTEMTRAY_H

systemtray.cpp

Als Nächstes schreiben wir den Klassenquellcode für die Arbeit mit System Tray , aber wir implementieren die Signalisierung nur bei der Interaktion mit Menüelementen und dem Symbol in der Taskleiste. Signalverarbeitungslogik wird in QML implementiert.

#include "systemtray.h"
#include <QMenu>
#include <QSystemTrayIcon>

SystemTray::SystemTray(QObject *parent) : QObject(parent)
{

    // Создаём контекстное меню с двумя пунктами
    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);

    /* Инициализируем иконку трея, устанавливаем иконку,
     * а также задаем всплывающую подсказку
     * */
    trayIcon = new QSystemTrayIcon();
    trayIcon->setContextMenu(trayIconMenu);
    trayIcon->setIcon(QIcon(":/logo-min.png"));
    trayIcon->show();
    trayIcon->setToolTip("Tray Program" "\n"
                         "Работа со сворачиванием программы трей");

    /* Также подключаем сигнал нажатия на иконку к обработчику
     * данного нажатия
     * */
    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
}

/* Метод, который обрабатывает нажатие на иконку приложения в трее
 * */
void SystemTray::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason){
    case QSystemTrayIcon::Trigger:
        // В случае сигнала нажатия на иконку трея вызываем сигнал в QML слой
        emit signalIconActivated();
        break;
    default:
        break;
    }
}

void SystemTray::hideIconTray()
{
    trayIcon->hide();
}

main.qml

Um auf die Eigenschaften des SystemTray -Klassenobjekts im Qml -Layer zuzugreifen, schreiben wir das Connections -Objekt, über das die Verbindung zum SystemTray-Objekt hergestellt wird. in das Target -Eigenschaft schreiben wir den Namen, der in der Datei main.cpp deklariert wurde, als die Qml -Engine über die setContextProperty()-Methode auf das Taskleistenobjekt zugegriffen hat.

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")

    // Переменная для игнорирования чекбокса
    property bool ignoreCheck: false

    /* С помощью объекта Connections
     * Устанавливаем соединение с классом системного трея
     * */
    Connections {
        target: systemTray
        // Сигнал - показать окно
        onSignalShow: {
            application.show();
        }

        // Сигнал - закрыть приложения игнорируя чек-бокс
        onSignalQuit: {
            ignoreCheck = true
            close();
        }

        // Свернуть/развернуть окно через клик по системному трею
        onSignalIconActivated: {
             if(application.visibility === Window.Hidden) {
                 application.show()
             } else {
                 application.hide()
             }
        }
    }

    // Тестовый чекбокс для управления закрытием окна
    CheckBox {
        id: checkTray
        anchors.centerIn: parent
        text: qsTr("Включить сворачивание в системный трей при нажатии кнопки закрытия окна")
    }

    // Обработчик события закрытия окна
    onClosing: {
        /* Если чекбокс не должен игнорироваться и он активен,
         * то скрываем приложение.
         * В противном случае закрываем приложение
         * */
        if(checkTray.checked === true && ignoreCheck === false){
            close.accepted = false
            application.hide()
        } else {
            // Завершаем приложение
            Qt.quit()
        }
    }
}

Zweite Option

Kommen wir nun zur zweiten Implementierungsoption, die in Zusammenarbeit mit Konstantin Lyashkevich geschrieben wurde.

Projektstruktur

In diesem Fall besteht die Projektstruktur nur aus:

    • QmlSystemTray.pro - Projektprofil;
  • main.cpp - Hauptquellcodedatei zum Ausführen der Anwendung;
  • main.qml - Datei mit dem Hauptanwendungsfenster;
  • logo-min.png - jedes Symbol, das in der Taskleiste platziert wird.

QmlSystemTray_2.pro

In diesem Fall empfehle ich, auf die Module zu achten, die im Projekt verbunden sind. Denn auf das Modul quickwidgets kann man nicht verzichten.

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)

main.cpp

Außerdem muss die Bibliothek QQuickWidget in die Quelldatei main.cpp. aufgenommen werden. Dies ist erforderlich, um die Funktion qmlRegisterType. zu verwenden.

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QIcon>
#include <QQuickWidget>
#include <QSystemTrayIcon>
#include <QQmlContext>

// Объявляем пользовательский тип данных для работы с иконкой в QML
Q_DECLARE_METATYPE(QSystemTrayIcon::ActivationReason)

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine; // Инициализируем Qml движок

    // Регистрируем QSystemTrayIcon в качестве типа объекта в Qml
    qmlRegisterType<QSystemTrayIcon>("QSystemTrayIcon", 1, 0, "QSystemTrayIcon");
    // Регистрируем в QML тип данных для работы с получаемыми данными при клике по иконке
    qRegisterMetaType<QSystemTrayIcon::ActivationReason>("ActivationReason");
    // Устанавливаем Иконку в контекст движка
    engine.rootContext()->setContextProperty("iconTray", QIcon(":/logo-min.png"));
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml

Als Nächstes deklarieren wir das Objekt QSystemTrayIcon und richten es in der Methode onCompleted des übergebenen Werts reason ein, um die Reaktion auf Mausklicks auf das Anwendungssymbol in der Taskleiste zu bestimmen. Wenn wir mit der rechten Maustaste auf das Anwendungssymbol in der Taskleiste klicken, erscheint Menü. Das Menü wird von der Funktion popup() aufgerufen. Das Merkmal der Funktion ist, dass sie das Menü an der Stelle aufruft wo sich der Mauszeiger befindet , sodass das Menü an der Stelle des Taskleistensymbols angezeigt wird.

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")

    // Зарегистрированный системный трей в QML слое
    QSystemTrayIcon {
        id: systemTray

        // Первоначальная инициализация системного трея
        Component.onCompleted: {
            icon = iconTray             // Устанавливаем иконку
            // Задаём подсказку для иконки трея
            toolTip = "Tray Program
Работа со сворачиванием программы трей"
            show();
        }

        /* По клику на иконку трея определяем,
         * левой или правой кнопкой мыши был клик.
         * Если левой, то скрываем или открываем окно приложения.
         * Если правой, то открываем меню системного трея
         * */
        onActivated: {
            if(reason === 1){
                trayMenu.popup()
            } else {
                if(application.visibility === Window.Hidden) {
                    application.show()
                } else {
                    application.hide()
                }
            }
        }
    }

    // Меню системного трея
    Menu {
        id: trayMenu

        MenuItem {
            text: qsTr("Развернуть окно")
            onTriggered: application.show()
        }

        MenuItem {
            text: qsTr("Выход")
            onTriggered: {
                systemTray.hide()
                Qt.quit()

            }
        }
    }

    // Тестовый чекбокс для управления закрытием окна
    CheckBox {
        id: checkTray
        anchors.centerIn: parent
        text: qsTr("Включить сворачивание в системный трей при нажатии кнопки закрытия окна")
    }

    // Обработчик события закрытия окна
    onClosing: {
        /* Если чекбокс не должен игнорироваться и он активен,
         * то скрываем приложение.
         * В противном случае закрываем приложение
         * */
        if(checkTray.checked === true){
            close.accepted = false
            application.hide()
        } else {
            // Завершаем приложение
            Qt.quit()
        }
    }
}

Insgesamt

Als Ergebnis der geleisteten Arbeit erhalten Sie eine Anwendung, die sowohl durch Klicken auf das Symbol in der Taskleiste als auch durch Drücken der Schaltfläche zum Schließen des Anwendungsfensters in die Taskleiste minimiert wird. Es wird wie auf dem Bild unten aussehen. Nun, Sie können eine Demonstration der Anwendung im Video-Tutorial sehen, das beide Optionen für den Programmcode erklärt.

Mitautor des Artikels: Konstantin Lyashkevich

Videoanleitung

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

o
  • 3. April 2017 17:13

Здравствуйте. В первом варианте не выложен файл QmlSystemTray.pro без него как-то не полно.

Evgenii Legotckoi
  • 4. April 2017 02:33

Добрый день. Добавил QmlSystemTray.pro.

o
  • 4. April 2017 02:34

Спасибо)

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken