이 페이지에서

시스템 트레이 아이콘 예제

시스템 트레이 아이콘 예제는 메뉴와 팝업 메시지가 포함된 아이콘을 데스크톱 환경의 시스템 트레이에 추가하는 방법을 보여줍니다.

네트워크 문제와 관련된 시스템 트레이 팝업

시스템 트레이 아이콘 스크린샷

최신 운영 체제는 일반적으로 바탕화면에 ‘시스템 트레이’ 또는 ‘알림 영역’이라고 하는 특별한 영역을 제공하며, 여기에서 장시간 실행되는 애플리케이션은 아이콘과 짧은 메시지를 표시할 수 있습니다.

이 예제는 하나의 클래스( Window)로 구성되어 있으며, 메인 애플리케이션 창(즉, 시스템 트레이 아이콘 편집기)과 관련 아이콘을 제공합니다.

팝업 제목, 표시 시간, 메시지 등 다양한 설정을 편집할 수 있는 시스템 트레이 편집기

이 편집기를 통해 사용자는 원하는 아이콘을 선택할 수 있을 뿐만 아니라, 풍선 메시지의 유형과 표시 시간을 설정할 수 있습니다. 또한 사용자는 메시지의 제목과 본문을 편집할 수도 있습니다. 마지막으로, 이 편집기에는 아이콘을 시스템 트레이에 실제로 표시할지 여부를 제어하는 확인란이 제공됩니다.

창 클래스 정의

Window 클래스는 QWidget 을 상속받습니다:

class Window : public QDialog
{
    Q_OBJECT

public:
    Window();

    void setVisible(bool visible) override;

protected:
    void closeEvent(QCloseEvent *event) override;

private slots:
    void setIcon(int index);
    void iconActivated(QSystemTrayIcon::ActivationReason reason);
    void showMessage();
    void messageClicked();

private:
    void createIconGroupBox();
    void createMessageGroupBox();
    void createActions();
    void createTrayIcon();

    QGroupBox *iconGroupBox;
    QLabel *iconLabel;
    QComboBox *iconComboBox;
    QCheckBox *showIconCheckBox;

    QGroupBox *messageGroupBox;
    QLabel *typeLabel;
    QLabel *durationLabel;
    QLabel *durationWarningLabel;
    QLabel *titleLabel;
    QLabel *bodyLabel;
    QComboBox *typeComboBox;
    QSpinBox *durationSpinBox;
    QLineEdit *titleEdit;
    QTextEdit *bodyEdit;
    QPushButton *showMessageButton;

    QAction *minimizeAction;
    QAction *maximizeAction;
    QAction *restoreAction;
    QAction *quitAction;

    QSystemTrayIcon *trayIcon;
    QMenu *trayIconMenu;
};

사용자 상호작용에 대응하기 위해 몇 가지 비공개 슬롯을 구현합니다. 나머지 비공개 함수들은 생성자를 단순화하기 위해 제공된 편의 함수일 뿐입니다.

트레이 아이콘은 ` QSystemTrayIcon ` 클래스의 인스턴스입니다. 사용자의 바탕 화면에 시스템 트레이가 있는지 확인하려면 정적 함수 ` QSystemTrayIcon::isSystemTrayAvailable()`를 호출하십시오. 아이콘과 연계하여, 일반적인 ` minimize`, ` maximize`, ` restore ` 및 ` quit ` 동작을 포함하는 메뉴를 제공합니다. QWidget::setVisible() 함수를 재구현하여, 메인 애플리케이션 창을 최대화하거나 최소화하는 등 편집기의 상태가 변경될 때마다 트레이 아이콘의 메뉴를 업데이트합니다.

마지막으로, QWidget 의 closeEvent() 함수를 재구현하여, (에디터 창을 닫을 때) 사용자가 아이콘의 컨텍스트 메뉴에서 ' Quit ' 항목을 선택할 때까지 프로그램이 시스템 트레이에서 계속 실행된다는 사실을 사용자에게 알릴 수 있도록 합니다.

창 클래스 구현

에디터 위젯을 생성할 때, 실제 시스템 트레이 아이콘을 생성하기 전에 먼저 다양한 에디터 요소들을 생성합니다:

Window::Window()
{
    createIconGroupBox();
    createMessageGroupBox();

    iconLabel->setMinimumWidth(durationLabel->sizeHint().width());

    createActions();
    createTrayIcon();

    connect(showMessageButton, &QAbstractButton::clicked, this, &Window::showMessage);
    connect(showIconCheckBox, &QAbstractButton::toggled, trayIcon, &QSystemTrayIcon::setVisible);
    connect(iconComboBox, &QComboBox::currentIndexChanged,
            this, &Window::setIcon);
    connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &Window::messageClicked);
    connect(trayIcon, &QSystemTrayIcon::activated, this, &Window::iconActivated);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(iconGroupBox);
    mainLayout->addWidget(messageGroupBox);
    setLayout(mainLayout);

    iconComboBox->setCurrentIndex(1);
    trayIcon->show();

    setWindowTitle(tr("Systray"));
    resize(400, 300);
}

응용 프로그램이 사용자 입력에 반응하도록 하기 위해, 편집기의 대부분의 입력 위젯(시스템 트레이 아이콘 포함)을 응용 프로그램의 비공개 슬롯에 연결합니다. 하지만 가시성 체크박스는 예외입니다. 이 체크박스의 ` toggled()` 신호는 대신 아이콘의` setVisible()` 함수에 연결되어 있습니다.

void Window::setIcon(int index)
{
    QIcon icon = iconComboBox->itemIcon(index);
    trayIcon->setIcon(icon);
    setWindowIcon(icon);

    trayIcon->setToolTip(iconComboBox->itemText(index));
}

setIcon() 슬롯은 아이콘 콤보박스의 현재 인덱스가 변경될 때마다, 즉 사용자가 편집기에서 다른 아이콘을 선택할 때마다 트리거됩니다. 또한 사용자가 마우스 왼쪽 버튼으로 트레이 아이콘을 활성화하여 아이콘의 activated() 신호를 트리거할 때도 호출된다는 점에 유의하십시오. 이 신호에 대해서는 잠시 후에 다시 다루겠습니다.

QSystemTrayIcon::setIcon() 함수는 실제 시스템 트레이 아이콘을 저장하는 icon 속성을 설정합니다. Windows에서 시스템 트레이 아이콘의 크기는 16x16이며, X11에서는 권장 크기가 22x22입니다. 아이콘은 필요에 따라 적절한 크기로 조정됩니다.

X11에서는 시스템 트레이 사양의 제한으로 인해 아이콘의 투명한 영역을 마우스로 클릭하면 클릭 이벤트가 시스템 트레이로 전달된다는 점에 유의하십시오. 이러한 동작이 허용되지 않는 경우, 투명도가 없는 아이콘을 사용하는 것이 좋습니다.

void Window::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason) {
    case QSystemTrayIcon::Trigger:
    case QSystemTrayIcon::DoubleClick:
        iconComboBox->setCurrentIndex((iconComboBox->currentIndex() + 1) % iconComboBox->count());
        break;
    case QSystemTrayIcon::MiddleClick:
        showMessage();
        break;
    default:
        ;
    }
}

사용자가 시스템 트레이 아이콘을 활성화할 때마다, 아이콘은 트리거 원인을 매개변수로 전달하며 ` activated()` 신호를 발생시킵니다. ` QSystemTrayIcon `는 아이콘이 어떻게 활성화되었는지를 설명하기 위해 ` ActivationReason ` 열거형을 제공합니다.

생성자에서 아이콘의 activated() 신호를 사용자 정의 iconActivated() 슬롯에 연결했습니다: 사용자가 마우스 왼쪽 버튼으로 아이콘을 클릭한 경우, 이 함수는 아이콘 콤보박스의 현재 인덱스를 증가시켜 아이콘 이미지를 변경하며, 앞서 언급한 대로 setIcon() 슬롯을 트리거합니다. 사용자가 마우스 가운데 버튼으로 아이콘을 활성화하면 사용자 정의 showMessage() 슬롯이 호출됩니다:

void Window::showMessage()
{
    showIconCheckBox->setChecked(true);
    int selectedIcon = typeComboBox->itemData(typeComboBox->currentIndex()).toInt();
    QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon(selectedIcon);

    if (selectedIcon == -1) { // custom icon
        QIcon icon(iconComboBox->itemIcon(iconComboBox->currentIndex()));
        trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon,
                          durationSpinBox->value() * 1000);
    } else {
        trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), msgIcon,
                          durationSpinBox->value() * 1000);
    }
}

showMessage() 슬롯이 트리거되면, 먼저 현재 선택된 메시지 유형에 따라 메시지 아이콘을 가져옵니다. QSystemTrayIcon::MessageIcon 열거형은 풍선 메시지가 표시될 때 나타나는 아이콘을 정의합니다. 그런 다음 QSystemTrayIcon 의 showMessage() 함수를 호출하여 지정된 밀리초 동안 제목, 본문 및 아이콘이 포함된 메시지를 표시합니다.

macOS 사용자 참고: QSystemTrayIcon::showMessage()이 메시지를 표시하려면 Growl 알림 시스템이 설치되어 있어야 합니다.

QSystemTrayIcon 또한 messageClicked() 신호도 있는데, 이는 사용자가 showMessage()에 의해 표시된 메시지를 클릭할 때 발생합니다.

void Window::messageClicked()
{
    QMessageBox::information(nullptr, tr("Systray"),
                             tr("Sorry, I already gave what help I could.\n"
                                "Maybe you should try asking a human?"));
}

생성자에서, 우리는 messageClicked() 신호를 QMessageBox 클래스를 사용하여 단순히 메시지를 표시하는 사용자 정의 messageClicked() 슬롯에 연결했습니다.

QMessageBox 는 짧은 메시지, 아이콘, 그리고 현재 스타일에 따라 배치된 버튼을 포함하는 모달 대화 상자를 제공합니다. 이 기능은 “질문(Question)”, “정보(Information)”, “경고(Warning)”, “중요(Critical)”의 네 가지 심각도 수준을 지원합니다. Qt에서 메시지 상자를 표시하는 가장 쉬운 방법은 관련 정적 함수 중 하나, 예를 들어 QMessageBox::information()를 호출하는 것입니다.

앞서 언급했듯이, 우리는 QWidget 의 가상 함수 중 몇 가지를 재구현합니다:

void Window::setVisible(bool visible)
{
    minimizeAction->setEnabled(visible);
    maximizeAction->setEnabled(!isMaximized());
    restoreAction->setEnabled(isMaximized() || !visible);
    QDialog::setVisible(visible);
}

QWidget::setVisible() 함수에 대한 우리의 재구현은 메인 애플리케이션 창을 최대화하거나 최소화하는 등 편집기의 외관이 변경될 때마다 트레이 아이콘의 메뉴를 업데이트한 후, 기본 클래스 구현을 호출합니다.

void Window::closeEvent(QCloseEvent *event)
{
    if (!event->spontaneous() || !isVisible())
        return;
    if (trayIcon->isVisible()) {
        QMessageBox::information(this, tr("Systray"),
                                 tr("The program will keep running in the "
                                    "system tray. To terminate the program, "
                                    "choose <b>Quit</b> in the context menu "
                                    "of the system tray entry."));
        hide();
        event->ignore();
    }
}

위젯 닫기 이벤트를 수신하기 위해 ` QWidget::closeEvent()` 이벤트 핸들러를 재구현했으며, 사용자가 편집기 창을 닫을 때 위와 같은 메시지를 표시합니다. 사용자가 실제로 애플리케이션을 종료하려는 경우, 즉 메뉴 바나 트레이 아이콘의 컨텍스트 메뉴에서 “종료”를 선택했거나 macOS에서 Command+Q 단축키를 누른 경우에는 메시지 표시를 피하고 닫기 이벤트를 수락해야 합니다.

앞서 설명한 함수와 슬롯 외에도, 생성자를 단순화하기 위해 다음과 같은 편의 함수들을 구현했습니다: createIconGroupBox(), createMessageGroupBox(), createActions() 및 createTrayIcon(). 자세한 내용은 desktop/systray/window.cpp 파일을 참조하십시오.

코드 예제 프로젝트 @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.