views:

79

answers:

2

How do I properly implement a "minimize to tray" function in Qt?

I tried the following code inside QMainWindow::changeEvent(QEvent *e), but the window simply minimizes to the taskbar and the client area appears blank white when restored.

if (Preferences::instance().minimizeToTray())
{
    e->ignore();
    this->setVisible(false);
}

Attempting to ignore the event doesn't seem to do anything, either.

+1  A: 
 void main_window::create_tray_icon()
 {
    m_tray_icon = new QSystemTrayIcon(QIcon(":/icon.png"), this);

    connect( m_tray_icon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_show_hide(QSystemTrayIcon::ActivationReason)) );

    QAction *quit_action = new QAction( "Exit", m_tray_icon );
    connect( quit_action, SIGNAL(triggered()), this, SLOT(on_exit()) );

    QAction *hide_action = new QAction( "Show/Hide", m_tray_icon );
    connect( hide_action, SIGNAL(triggered()), this, SLOT(on_show_hide()) );

    QMenu *tray_icon_menu = new QMenu;
    tray_icon_menu->addAction( hide_action );
    tray_icon_menu->addAction( quit_action );

    m_tray_icon->setContextMenu( tray_icon_menu );

    m_tray_icon->show();
  }

void main_window::on_show_hide( QSystemTrayIcon::ActivationReason reason )
{
    if( reason )
    {
        if( reason != QSystemTrayIcon::DoubleClick )
        return;
    }

    if( isVisible() )
    {
        hide();
    }
    else
    {
        show();
        raise();
        setFocus();
    }
}

That's how I realize a "minimize to tray". You can now minimize either by double clicking on the icon, or by right-clicking and selecting "Show/Hide" in the menu.

Exa
Thanks, but I am specifically looking for a way to hide the window when the user minimizes it. ;)
Jake Petroules
Ah okay, sorry, got you wrong there :) So now it's just an example for those who need an working icon with show/hide-functions :)
Exa
+1 for a nice code!
Narek
+1  A: 

Apparently a small delay is needed to process other events (perhaps someone will post the exact details?). Here's what I ended up doing, which works perfectly:

void MainWindow::changeEvent(QEvent* e)
{
    switch (e->type())
    {
        case QEvent::LanguageChange:
            this->ui->retranslateUi(this);
            break;
        case QEvent::WindowStateChange:
            {
                if (this->windowState() & Qt::WindowMinimized)
                {
                    if (Preferences::instance().minimizeToTray())
                    {
                        QTimer::singleShot(250, this, SLOT(hide()));
                    }
                }

                break;
            }
        default:
            break;
    }

    QMainWindow::changeEvent(e);
}
Jake Petroules
Interesting fact that it requires a delay to work, but very useful :) Would like to know if there's a "cleaner" solution though.. But I will try your code, too :)
Exa