Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt system tray context menu remains when app loses focus

I've set up a system tray icon for my app and have attached a simple context menu to it. If I right click the icon to bring up the context menu it works fine. If I then click somewhere that loses the focus of the app (e.g. elsewhere on the task bar or on another app) the context menu is not removed and still triggers the correct action when clicked. If, however, I click on the main app the context menu disappears as expected.

Here's the relevant code for creating the tray icon and context menu -

actionExit = new QAction( "Exit", this );
connect( actionExit, SIGNAL( triggered() ), this, SLOT( ExitClient() ));

myTrayIconMenu = new QMenu( this );
myTrayIconMenu->addAction( actionExit );

trayIcon = new QSystemTrayIcon( icon, this );
trayIcon->setContextMenu( myTrayIconMenu );
connect( systrayIcon, SIGNAL( activated( QSystemTrayIcon::ActivationReason )), 
         this, SLOT( ToggleVisibility( QSystemTrayIcon::ActivationReason )));
trayIcon->show( );

Do I need to add my own code that tests for the app losing focus so that I can manually hide the context menu? I had assumed this functionality would be built in.

[The problem is occurring in Windows 7, compiling with Visual Studio 2010 Pro via Qt plug-in - I haven't tested under any other OS]

I noticed this in the API documentation -

Note: The system tray icon does not take ownership of the menu. You must ensure that it is deleted at the appropriate time by, for example, creating the menu with a suitable parent object.

If I use

myTrayIconMenu = new QMenu( );

instead of

myTrayIconMenu = new QMenu( this );

the context menu is removed when the app loses focus. But then I'll need to take care of manually deleting the context menu.

How have other people dealt with this situation?

like image 396
Rok Avatar asked Nov 05 '22 21:11

Rok


1 Answers

Implementing a QSystemTrayIcon in your QApplication derived class instead of some QWidget can fix this issue.

main.cpp:

int main(int argc, char *argv[])
{
    return TestApp(argc, argv).exec();
}

testApp.cpp:

TestApp::TestApp(int &argc, char **argv) :
    QApplication(argc, argv)
{
    quitAction = new QAction("quit", this);
    connect(quitAction, SIGNAL(triggered()), this, SLOT(quit()));
    systemTrayMenu = new QMenu("tray menu");
    systemTrayMenu->addAction(quitAction);

    trayIcon = new QSystemTrayIcon( this);
    trayIcon -> setToolTip("test app");
    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
    trayIcon -> setContextMenu(systemTrayMenu);
    trayIcon -> show();
}
like image 126
Colin.Z Avatar answered Nov 12 '22 17:11

Colin.Z