システムトレイアイコンの例

システム トレイ アイコンの例では、デスクトップ環境のシステム トレイにメニューとポップアップ メッセージを備えたアイコンを追加する方法を示します。

システムトレイアイコンのスクリーンショット

最近のオペレーティングシステムは通常、システムトレイまたは通知領域と呼ばれるデスクトップ上の特別な領域を提供し、そこで長時間実行されるアプリケーションはアイコンと短いメッセージを表示することができます。

この例では、メイン・アプリケーション・ウィンドウ(すなわち、システム・トレイ・アイコンのエディタ)と関連するアイコンを提供する1つのクラス、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 ()関数を呼び出します。アイコンに関連して、典型的なminimizemaximizerestorequit アクションを含むメニューを提供します。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() シグナルを発し、トリガーとなった理由をパラメータとして渡します。QSystemTrayIconActivationReason enum を提供し、アイコンがどのようにアクティブになったかを記述します。

コンストラクタでは、アイコンの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 enumは、バルーンメッセージが表示されるときに表示されるアイコンを記述します。次に、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 は、短いメッセージ、アイコン、および現在のスタイルに応じてレイアウトされたボタンを持つモーダルダイアログを提供します。4つの重要度レベルをサポートしています:「Question"、"Information"、"Warning"、"Critical "です。Qtでメッセージ・ボックスをポップアップする最も簡単な方法は、関連するスタティック関数の1つ、例えば () を呼び出すことです。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() イベントハンドラを再実装して、ウィジェットのクローズイベントを受け取り、エディタウィンドウを閉じるときに上記のメッセージをユーザーに表示します。ユーザが本当にアプリケーションを終了しようとしているとき、つまり、ユーザがメニューバーやトレイアイコンのコンテキストメニューで "Quit "をトリガーしたとき、あるいはmacOSでCommand+Qショートカットを押したときに、メッセージを表示したり、クローズイベントを受け取ったりしないようにする必要があります。

上述した関数とスロットに加えて、コンストラクタを簡素化するためにいくつかの便利な関数を実装しました:createIconGroupBox() createMessageGroupBox()createActions()createTrayIcon() 。詳しくはdesktop/systray/window.cpp ファイルをご覧ください。

サンプルプロジェクト @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。