Implementing Minimize To Tray Functionality Using Qt/C++

I wanted to create my own personal stand-alone YouTube Player with Minimize to System Tray functionality. In other words I wanted it to be minimized to the System Tray when I closed it and displayed again when I clicked its icon in System Tray. I actually did it the other day and the whole thing led to this post. So, in this post I’ll describe How to use Qt/C++ to create your own YouTube Player with Minimize to Tray functionality in less than 10 minutes.



Start by creating a new Qt Widgets Application project in Qt Creator.

Name it YTPlayer or something similar and make sure you choose a Qt Kit that has support for Qt WebEngine Module (including Qt WebEngine Widgets).

Qt WebEngine is a nice wrapper around Chromium and it allows embedding Web Content (such as YouTube) in your Qt Applications.

After the project is created, you must modify the project file (*.pro) to add Qt WebEngine Widgets supports to it. This can be done by adding the following line to the project file:

QT += webenginewidgets

You can also add webenginewidgets to the list of existing modules (core, gui and so on), either way, you need to run qmake once again to make sure project file is reprocessed.

Next, from Qt Designer, add a Widget to the GUI, name it webView and then press CTRL+G to lay out everything in a grid on your GUI. You can also get rid of the existing empty menus, toolbars and anything that Qt Creator had added to the GUI by default.

Now you need to promote the webView widget to QWebEngineView, since it’s just a soulless QWidget at the moment. Promotion of a widget to another one is only possible if they have common ancestors. Here’s a screenshot that shows how it’s done, after right clicking on the widget from Qt Designer and choosing Promote to from the available items.



Now it’s time to write the required codes and make YTPlayer function for real. Start by adding the following to MainWindow class, in mainwindow.h file:

protected:
    void closeEvent(QCloseEvent *event) override;

This is required for handling close events in Qt windows. The other thing we need to add is the following flag, which is required for actual close detection:

private:
    bool closing;

Now you need to add the following include directives in mainwindow.cpp file:

#include <QSystemTrayIcon>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
#include <QCloseEvent>

You can add them to mainwindow.h as well. The next thing we need to do, is to add the following to the MainWindow constructor:

ui->webView->setUrl({"https://youtube.com"});

closing = false;

auto exitAction = new QAction(tr("&Exit"), this);
connect(exitAction, &QAction::triggered, [this]()
{
    closing = true;
    close();
});

auto trayIconMenu = new QMenu(this);
trayIconMenu->addAction(exitAction);

auto sysTrayIcon = new QSystemTrayIcon(this);
sysTrayIcon->setContextMenu(trayIconMenu);
sysTrayIcon->setIcon(QIcon(":/icon.ico"));
sysTrayIcon->show();


In the preceding code, first we load the YouTube website in our webView, then create the menu for the tray icon using a QMenu and a QAction. The next step is to create a QSystemTrayIcon and set a QIcon on it, pretty straightforward. The important part is that QSystemTrayIcon must have an icon or displaying it won’t be possible.

To add an icon to QSystemTrayIcon, you must first add a Qt Resource file to your project and then add an icon of your choice into the resources. You just need to make sure it’s named icon.ico to be compatible with the preceding code sample.

The next important piece of code is the part where we handle clicking on the tray icon. You can add that to the MainWindow constructor as well. Here it is:

connect(sysTrayIcon, &QSystemTrayIcon::activated, [this](auto reason)
{
    if(reason == QSystemTrayIcon::Trigger)
    {
        if(isVisible())
        {
            hide();
        }
        else
        {
            show();
            activateWindow();
        }
    }
});

With that, the only thing remaining is to handle the actual closing and to do that you need to add the following to mainwindow.cpp file:

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(closing)
    {
        event->accept();
    }
    else
    {
        this->hide();
        event->ignore();
    }
}


Here is the result of this post and my own YTPlayer:



Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.