Pemrograman Qt 20 – QSystemTrayIcon untuk Membuat Aplikasi System Tray


Bismillahirrahmanirrahim.

Tulisan ini tersedia dalam PDF.

qt-creator-logoApa Anda ingin membuat aplikasi system tray? Aplikasi semacam ini punya fasilitas ikon di pojok kiri bawah panel menu desktop ala KDE atau di kiri atas pada panel menu ala GNOME. Contoh aplikasi yang memakai fitur ini misalnya antivirus, audio playersound appletdownload manager, dan lain-lain. Ciri khas aplikasi dengan fitur ini adalah jika ditutup jendelanya maka dia tidak hilang tetapi bertengger di lokasi system tray. Kita akan membuatnya dengan berdasarkan pada contoh kode dari dokumentasi resmi Qt Framework sendiri yang sudah ada di dalam Qt Creator. Saya berusaha memodifikasi program contoh Qt yang bernama systray sehingga tersisa hanya fungsi-fungsi paling minimal untuk sebuah program system tray. Saya lakukan ini karena ingin tahu bagaimana kode paling minimal untuk program system tray itu dan alhamdulillah berhasil. Semoga tulisan ini bermanfaat.

Spesifikasi Sistem

  1. Ubuntu 12.04
  2. Qt Creator 2.4.1
  3. Qt 4.8

Daftar Kelas

  1. QSystemTrayIcon
  2. QMenu
  3. QAction
  4. QIcon
  5. QMessageBox

Daftar Method

  1. addAction() -> milik QMenu
  2. addSeparator() -> milik QMenu
  3. setContextMenu() -> milik QMenu
  4. show() -> milik QSystemTrayIcon
  5. isVisible() -> milik QSystemTrayIcon
  6. ignore() -> milik QCloseEvent
  7. information() -> milik QMessageBox
  8. createActions() -> buatan sendiri
  9. createTrayIcon() -> buatan sendiri
  10. iconActivated() -> buatan sendiri
  11. closeEvent() -> buatan sendiri

Arah Tulisan Ini

ngite-keduapuluh11

uGet

ngite-keduapuluh9

Quassel

Program yang akan dibuat adalah program dengan kemampuan bertengger di system tray semisal download manager (uGet) dan IRC client (Quassel).

Kode

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui>

namespace Ui
{
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QVBoxLayout     *layoutUtama;
    QPushButton     *tombolUtama;
    QWidget         *widgetUtama;

    QAction         *minimize;
    QAction         *maximize;
    QAction         *restore;
    QAction         *quit;

    QSystemTrayIcon *trayIcon;
    QMenu           *trayIconMenu;

    QIcon           *ikon;

private:
    Ui::MainWindow   *ui;

private slots:
    void createActions();
    void createTrayIcon();
//    void iconActivated(QSystemTrayIcon::ActivationReason reason);     //ini berhubungan dengan fungsi iconActivated() di mainwindow.cpp

protected:
    void closeEvent(QCloseEvent *event);

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    //deklarasi objek-objek GUI
    QVBoxLayout     *layoutUtama    =   new     QVBoxLayout;
    QPushButton     *tombolUtama    =   new     QPushButton("TOMBOL");
    QWidget         *widgetUtama    =   new     QWidget;

    //pemanggilan fungsi penting yang akan selalu berjalan
    createActions();
    createTrayIcon();

    //pemasangan layout kepada widget
    layoutUtama->addWidget(tombolUtama);
    widgetUtama->setLayout(layoutUtama);
    this->setCentralWidget(widgetUtama);

    //SIGNAL AND SLOT
//    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
//            this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));        //ini dijadikan komentar karena bukan komponen paling minimal untuk program system tray

    //mengurus ikon untuk system tray
    trayIcon->setIcon(QIcon(":/gambar/metamorfosa"));
    trayIcon->show();       //tanpa baris ini, system tray tidak akan muncul sama sekali
                            //bahkan setelah jendela closed pun tidak

    //set logo untuk jendela supaya sama dengan ikon system tray
    this->setWindowIcon(QIcon(":/gambar/metamorfosa"));

}

MainWindow::~MainWindow()
{
    delete ui;
}

/*
  DAFTAR ISI

  1. iconActivated
  2. createActions
  3. createTrayIcon
  4. closeEvent
*/

//1. iconActivated
//fungsi ini mengatur perilaku klik kanan, klik kiri, dan klik tengah pada ikon system tray
/*//fungsi ini bukan termasuk fungsi paling minimal untuk program system tray sehingga tidak dipakai
//void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
//{
//    switch(reason)
//    {
//        case QSystemTrayIcon::Trigger:

//        case QSystemTrayIcon::DoubleClick:

//        case QSystemTrayIcon::MiddleClick:

//    default:
//    ;
//    }
//}*/

//2. createActions
//fungsi ini membuat objeck-objek Actions untuk menu klik kanan lalu menghubungkannya dengan fungsi jendela
void MainWindow::createActions()
{
    minimize    =   new QAction(tr("Minimize"), this);
    connect(minimize, SIGNAL(triggered()), this, SLOT(hide()));

    maximize    =   new QAction(tr("Maximize"), this);
    connect(maximize, SIGNAL(triggered()), this, SLOT(showMaximized()));

    restore     =   new QAction(tr("Restore"), this);
    connect(restore, SIGNAL(triggered()), this, SLOT(showNormal()));

    quit        =   new QAction(tr("Keluar"), this);
    connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
}

//3. createTrayIcon
//fungsi ini memasukkan action yang sudah dibuat dengan createActions ke dalam menu tray icon
//sejatinya, fungsi ini membuat objek QMenu lalu mengisinya dengan objek-objek QActions,
//lalu mengeset context menu dari QSystemTrayIcon dengan objek QMenu tadi
void MainWindow::createTrayIcon()
{
    trayIconMenu    =   new QMenu(this);
    trayIconMenu->addAction(minimize);
    trayIconMenu->addAction(maximize);
    trayIconMenu->addAction(restore);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(quit);

    trayIcon        =   new QSystemTrayIcon(this);
    trayIcon->setContextMenu(trayIconMenu);         //tanpa baris ini,
    //menu pada klik kanan
    //pada ikon di system tray tidak akan muncul
    //ditemukan pada Wednesday, June 04, 2014 10:14 PM
}

//4.closeEvent
//fungsi ini menayangkan dialog pesan ketika jendela ditutup lalu program bertengger di system tray
//fungsi ini protected
void MainWindow::closeEvent(QCloseEvent *event)
{
    if(trayIcon->isVisible())
    {
        QMessageBox::information(this, tr("Pesan"), tr("Aku akan bertengger di pojokan <i>system tray</i>-mu"));
        hide();
        event->ignore();
    }
}

Qt Creator dan Kode

ngite-keduapuluh4

Hasil

Tampilan yang dihasilkan sederhana saja. Tombol satu itu pun tidak diberi fungsi. 

ngite-keduapuluh1

Jika jendela ditutup, maka sebuah dialog QMessageBox akan muncul sebagai peringatan.

ngite-keduapuluh2

Setelah itu, ia menjadi ikon (saya memberikan ikon Archlinux kepadanya) pada bagian system tray di menubar. Ikon system tray ini bisa digunakan sebagaimana aplikasi system tray yang lain.

ngite-keduapuluh

Analisis

mainwindow.h

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QVBoxLayout     *layoutUtama;
    QPushButton     *tombolUtama;
    QWidget         *widgetUtama;

    QAction         *minimize;
    QAction         *maximize;
    QAction         *restore;
    QAction         *quit;

    QSystemTrayIcon *trayIcon;
    QMenu           *trayIconMenu;

    QIcon           *ikon;

Hal penting di dalam program kita kali ini adalah penggunaan kelas QSystemTrayIcon, QAction, dan QMenu. Sepanjang tutorial pemrograman Qt di blog ini, 3 kelas ini belum pernah dipakai. Jika Anda belum memahami cara deklarasi di dalam header ini, silakan merujuk ke penjelasan deklarasi header.

mainwindow.cpp

Pada mainwindow.cpp, ada 3 fungsi buatan yang penting. Sebelum itu, ada beberapa bagian penting di dalam kelas MainWindow. Dua fungsi ini (createActions() dan createTrayIcon()) dipanggil supaya hidup terus menerus. Dan jika Anda belum memahami cara membuat GUI pada berkas CPP ini, silakan merujuk ke penjelasan cara membuat GUI dasar.

    //pemanggilan fungsi penting yang akan selalu berjalan
    createActions();
    createTrayIcon();

Dua fungsi buatan yang paling penting ini dipanggil dahulu sebelum pemasangan layout.

1. createActions()

//1. createActions
//fungsi ini membuat objeck-objek Actions untuk menu klik kanan lalu menghubungkannya dengan fungsi jendela
void MainWindow::createActions()
{
    minimize    =   new QAction(tr("Minimize"), this);
    connect(minimize, SIGNAL(triggered()), this, SLOT(hide()));

    maximize    =   new QAction(tr("Maximize"), this);
    connect(maximize, SIGNAL(triggered()), this, SLOT(showMaximized()));

    restore     =   new QAction(tr("Restore"), this);
    connect(restore, SIGNAL(triggered()), this, SLOT(showNormal()));

    quit        =   new QAction(tr("Keluar"), this);
    connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
}

Sebelum mendeklarasikan objek-objek QAction ini di dalam fungsi ini, kita perlu mendeklarasikan dulu mereka di mainwindow.h. Argumen fungsi tr() adalah pengganti string biasa untuk keperluan penerjemahan pada masa mendatang. Tanpa tr(), kita tidak bisa membuat berkas .po atau semacamnya untuk penerjemahan antarmuka aplikasi sebagaimana biasa kita temukan di Transifex maupun Launchpad.

Pada fungsi createActions() di atas, kita melakukan connect() antara SIGNAL triggered() dengan SLOT fungsi hide(), showMaximized(), showNormal(), dan quit() dari jendela utama. Maksudnya jelas, agar setiap objek QAction memiliki tugasnya masing-masing. Khusus untuk quit(), objek kedua di dalam connect() bukan this melainkan qApp. Menurut QApplication Class Reference[1], qApp di sini adalah pointer global yang menunjuk kepada instansi QApplication. SLOT di sini memakai fungsi-fungsi dari QWidget berdasarkan dokumentasi QWidget Class Reference[2].

2. createTrayIcon()

//2. createTrayIcon
//fungsi ini memasukkan action yang sudah dibuat dengan createActions ke dalam menu tray icon
//sejatinya, fungsi ini membuat objek QMenu lalu mengisinya dengan objek-objek QActions,
//lalu mengeset context menu dari QSystemTrayIcon dengan objek QMenu tadi
void MainWindow::createTrayIcon()
{
    trayIconMenu    =   new QMenu(this);
    trayIconMenu->addAction(minimize);
    trayIconMenu->addAction(maximize);
    trayIconMenu->addAction(restore);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(quit);

    trayIcon        =   new QSystemTrayIcon(this);
    trayIcon->setContextMenu(trayIconMenu);         //tanpa baris ini,
    //menu pada klik kanan
    //pada ikon di system tray tidak akan muncul
    //ditemukan pada Wednesday, June 04, 2014 10:14 PM
}

Fungsi createTrayIcon() adalah tindak lanjut dari createActions() sebelumnya. Jika fungsi sebelumnya bertugas membuat aksi, maka fungsi ini bertugas memasang aksi itu pada menu klik kanan lalu membuat ikon system tray. Fungsi inilah sebetulnya yang menayangkan ikon aplikasi kita pada system tray dengan deklarasi objek trayIcon. Inti fungsi ini adalah deklarasi setContextMenu() dengan argumen objek QMenu. Objek QMenu bernama trayIconMenu, sudah diisi dengan objek-objek QAction pada baris-baris di atasnya.  Fungsi addSeparator() di atas berguna untuk menayangkan garis horizontal yang memisahkan 3 perintah dengan perintah Quit pada menu klik kanan nantinya.

3. closeEvent()

//3.closeEvent
//fungsi ini menayangkan dialog pesan ketika jendela ditutup lalu program bertengger di system tray
//fungsi ini protected
void MainWindow::closeEvent(QCloseEvent *event)
{
    if(trayIcon->isVisible())
    {
        QMessageBox::information(this, tr("Pesan"), tr("Aku akan bertengger di pojokan <i>system tray</i>-mu"));
        hide();
        event->ignore();
    }
}

Bagaimanakah aplikasi ini bisa tetap bertengger di system tray sementara jendela utama ditutup? Bagaimana dia bisa menayangkan jendela dialog berisi pesan? Fungsi closeEvent() ini jawabannya.

4. Satukan Semuanya

Setelah ketiga fungsi paling mendasar itu, saya jelaskan beberapa baris kode terpenting dalam MainWindow().

    //mengurus ikon untuk system tray
    trayIcon->setIcon(QIcon(":/gambar/metamorfosa"));
    trayIcon->show();       //tanpa baris ini, system tray tidak akan muncul sama sekali
                            //bahkan setelah jendela closed pun tidak

    //set logo untuk jendela supaya sama dengan ikon system tray
    this->setWindowIcon(QIcon(":/gambar/metamorfosa"));

Baris setIcon() di atas bertugas untuk memberikan ikon PNG Archlinux sebagai wujud program ini di system tray. Kemudian baris show() di atas berguna untuk menayangkan ikon dari program di dalam system tray. Kemudian baris setWindowIcon() di atas berguna untuk memberi logo Archlinux kepada jendela, supaya sama dengan ikon system tray-nya. Logo Archlinux ini sudah saya sertakan di tarball kode sumber di bawah.

Kesimpulan

  1.  Pembuatan program system tray paling minimal dengan Qt dilakukan dengan membuat objek-objek QAction, kemudian membuat objek QSystemTrayIcon dan QMenu, kemudian menyiapkan close event

Unduh Kode Sumber

Program kali ini bernama CalonSystemTray. Silakan unduh dan buka di Qt Creator Anda.

Referensi

  1. http://qt-project.org/doc/qt-4.8/qapplication.html
  2. http://qt-project.org/doc/qt-4.8/qwidget.html

Dilarang menggunakan emotikon

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s