18

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.

4

4 回答 4

19

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);
}
于 2010-07-26T08:04:23.187 回答
11

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...

于 2011-05-23T08:46:35.403 回答
8
 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.

于 2010-07-26T05:51:32.657 回答
0

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.

于 2018-07-30T16:13:51.003 回答