简体   繁体   中英

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

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.

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);
}

In addition to what Jake Petroules said, it appears that simply doing:

QTimer::singleShot(0, this, SLOT(hide()));

is enough. From http://qt-project.org/doc/qt-4.8/qtimer.html#details :

As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed.

This way you don't have the problem of selecting an appropriate delay value...

 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.

I have found that the showMinimized() slot works without a QTimer delay, so you can use code like:

mw->show();
if ( qApp->arguments().contains( "--startHidden" ) )
  mw->showMinimized();

in your main() to show a main window and immediately iconize it, when desired.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM