PDA

View Full Version : Minimize to system tray



aLiNuSh
17th April 2007, 04:54
Hi,

I have a subclassed QDialog and I implemented a QSystemTrayIcon for it, with some Show/Hide options.
What I want to do is to minimize the window to the tray when the minimize button is clicked. I managed to do it for the close button by reimplementing QDialog::closeEvent () but I want to do it for the minimize button.

So any solutions?

Thanks :)

marcel
17th April 2007, 04:58
You can use QWindowStateChangeEvent, and look at the current window state. This event must be handled in the event() function of your dialog.

Regards.

aLiNuSh
17th April 2007, 05:17
You can use QWindowStateChangeEvent, and look at the current window state. This event must be handled in the event() function of your dialog.

Regards.

So I could do something like...


void MyDialog::event (QEvent * event)
{
// i have no idea what i should write here, maybe like...
QWindowStateChangeEvent *qwsc_event = event;
Qt::WindowStates flag = qwsc_event->oldState ();
}

marcel
17th April 2007, 05:23
void MyDialog::event( QEvent *e )
{
if( e->type() == QEvent::WindowStateChange )
{
//Now check to see if the window is minimised
if( isMinimised() )
//Do something here (show the icon in the systray )
}
}

Should work

Edit:
don't do a dynamic cast at every event, instead check the event type

aLiNuSh
17th April 2007, 05:37
void MyDialog::event( QEvent *e )
{
if( e->type() == QEvent::WindowStateChange )
{
//Now check to see if the window is minimised
if( isMinimised() )
//Do something here (show the icon in the systray )
}
}

Should work

Edit:
don't do a dynamic cast at every event, instead check the event type

OK I will try it, but shouldn't I do something like forward the other events? How would I do that... like when an event is not a WindowStateChange how would I forward it for default processing? Should I do something like...



void MyDialog::event( QEvent *e )
{
if( e->type() == QEvent::WindowStateChange )
{
//Now check to see if the window is minimised
if( isMinimised() )
{
hide ();
e->ignore ();
}
}
else e->accept ();
}

marcel
17th April 2007, 05:45
Sure :).
It was just an on-the-fly example.
Of course you have to forward the other events.

Regards

aLiNuSh
17th April 2007, 06:12
Sure :).
It was just an on-the-fly example.
Of course you have to forward the other events.

Regards

Well actually the function returns a bool so I did this:



bool MyInstantMessenger::event (QEvent *e)
{
if(e->type() == QEvent::WindowStateChange)
{

//Now check to see if the window is minimised
if (isMinimized())
{
e->accept ();
hide ();
}
else e->ignore ();
return true;
}
e->ignore ();
return false;
}

But this messes my application, like the widgets are not drawn and the QCloseEvent is not sent anymore. I also tried setting other combinations like ignoring the message instead of accepting it and returning false instead of true but that didn't either.

Would installEventFilter() work too? I'm looking in to it right now...

jpn
17th April 2007, 06:20
One should pass the events to the base class implementation. Also, it's recommended to reimplement more specialized QWidget::changeEvent() instead of QWidget::event().


void MyInstantMessenger::changeEvent (QEvent *e)
{
if(e->type() == QEvent::WindowStateChange)
{
//Now check to see if the window is minimised
if (isMinimized())
{
hide ();
}
}
QDialog::changeEvent(e); // QDialog, or whatever the base class is
}

marcel
17th April 2007, 06:36
Yes, passing the ignored events to the base class will solve your problem.

aLiNuSh
17th April 2007, 08:06
That didn't help either :(
I also tried accepting and/or ignoring events and also didn't work, the window is still not hidden from the taskbar and the client area not painted.

marcel
17th April 2007, 08:17
bool MyInstantMessenger::event (QEvent *e)
{
if(e->type() == QEvent::WindowStateChange)
{
//Now check to see if the window is minimised
if (isMinimized())
{
hide ();
}
}
return QDialog::event( e );
}
]

Is this what you did?

EDIT: This is what you need to do. You have to let QDialog handle the change event. You must not accept nor ignore the event. Just hide your window.

regards

aLiNuSh
17th April 2007, 08:39
bool MyInstantMessenger::event (QEvent *e)
{
if(e->type() == QEvent::WindowStateChange)
{
//Now check to see if the window is minimised
if (isMinimized())
{
e->accept ();
hide ();
return true;
}
}
return QDialog::event( e );
}
]

Is this what you did?

Maybe... I tried so many different combinations I can't remember anymore.
Anyways I tried it now and it does the same thing... when I push the minimize button the window minimizes to the taskbar and the taskbar "button for the window" disappears and appears again quickly, and then when I maximize it, the window shows on the screen but the client area is not painted. Obviously it has to be something with some of the events not being forwarded for default processing... i just don't know what I'm missing here... :( :(

marcel
17th April 2007, 08:46
Could you show me the actual code? The one that you last tried :)

aLiNuSh
17th April 2007, 09:07
I just closed Notepad++ and deleted the code... basically I've tried reimplementing changeEvent () or event () sometimes accepting or rejecting the events, sometimes returning true or false or QWidget::changeEvent ()/event() and other different combinations.
I lost 4 hours on this stupid thing and still haven't got it working.

Anyways thanks for the assistance and maybe when I'll feel masochist enough I'll retry it :P

We're from the same country BTW :D

LE: tried the edited one too.. same thing :(

sheeeng
13th January 2009, 07:49
That didn't help either :(
I also tried accepting and/or ignoring events and also didn't work, the window is still not hidden from the taskbar and the client area not painted.

I faced the same problem.

Anyone has a solution to these issues?

Thanks in advance.

ssibitz
29th June 2009, 14:14
Hi !

I also have the problem with the systrayicon and minimize
so i try following ...


// Overload original event-handler:
bool MainWindow::event(QEvent *evt)
{
// Check if Window-State changed to minimize ...
if(evt->type() == QEvent::WindowStateChange)
{
//Now check to see if the window is minimised
if (isMinimized())
{
// Call the Hide Slot after 250ms
// to prozess other events ....
qApp->processEvents();
QTimer::singleShot(250, this, SLOT(hide()));
evt->ignore();
}
}
// Call original-handler (in this case QMainWindow ...)
return QMainWindow::event(evt);
}

... this work's on windows !

mkkguru
23rd February 2010, 11:44
Use the below code it might be helpful to you.......




//System tray icon action context menu

minimizeAction = new QAction(tr("Mi&nimize"), this);
connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));

maximizeAction = new QAction(tr("Ma&ximize"), this);
connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));

restoreAction = new QAction(tr("&Restore"), this);
connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));

quitAction = new QAction(tr("&Quit"), this);
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));

//ToolbarAction(itemExit).icon(), ToolbarAction(itemExit).text(), parent);
cmenu.addAction(tr("Show"), this, SLOT(show()));
cmenu.addAction(tr("Hide"), this, SLOT(hide()));
cmenu.addSeparator();
cmenu.addAction(minimizeAction);
cmenu.addAction(maximizeAction);
cmenu.addAction(restoreAction);
cmenu.addAction(quitAction);

Freetec
4th March 2010, 12:51
Hi, here is a solution, and I think it works quite well in my application:

In the dialog's slot that connects with the activated() signal of the QSystemTrayIcon object, use the setParent() function as:


void FtpDialog::sysTrayActivated(QSystemTrayIcon::Activ ationReason reason)
{
if (reason == QSystemTrayIcon::Trigger){
setParent(NULL, Qt::Window);
showNormal();
sysTrayIcon->hide();
}
}


And in the dialog's event() function:


bool FtpDialog::event(QEvent *e)
{
if (e->type() == QEvent::WindowStateChange) {
if (isMinimized()) {
setParent(tmp, Qt::SubWindow);
sysTrayIcon->show();
e->ignore();
qDebug()<<"event() called";
} else {
e->accept();
}

}
return QDialog::event(e); // return with QDialog's event() call anyway.
}

Here, 'tmp' is an empty QWidget serving as a provisional 'parent' of the dialog, so that the dialog can be hidden from task-bar when minimized. In fact, you can just pass NULL as the first argument for the 'parent' widget, but in this case probably the re-stored window would exhibit slightly different with the original window size.