Usually, the tools window is always at the top of the main window, even if it loses focus. However.
On MacOS, when the main window sets the window flag Qt::WindowStaysOnTopHint
, the Tool window is below it.
On a Windows system, the Tool window is at the top of the main window as expected.
Is there a way to keep the main window at the top while the Tool window is above it?
My current Qt versions are 5.9.6 and 5.12.1. The MacOS version is 10.13.4.
This is my test code
#include <QtGui>
#include <QtWidgets>
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
QDialog* mw = new QDialog(0, Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
mw->setWindowTitle(QLatin1String("Main"));
mw->resize(400, 300);
mw->move(100, 100);
QWidget* d = new QWidget(mw, Qt::Tool);
d->setWindowTitle(QLatin1String("Tool"));
d->resize(200, 100);
d->show();
mw->exec();
return app.exec();
}
Sorry, I have no MacOS system, however, I could reproduce and fix your problem under Ubuntu. Hopefully, it will work the same under MacOS.
First, bnaecker is right, you should call show()
rather than exec()
for your main window. Would be nice if it was a QMainWidget
rather than a QDialog
, but that's not the problem here.
According to the doc:
Qt::Tool: Indicates that the widget is a tool window. A tool window is often a small window with a smaller than usual title bar and decoration, typically used for collections of tool buttons. It there is a parent, the tool window will always be kept on top of it. If there isn't a parent, you may consider using Qt::WindowStaysOnTopHint as well. If the window system supports it, a tool window can be decorated with a somewhat lighter frame. It can also be combined with Qt::FramelessWindowHint.
Your tool widget, has a parent, so that should work. However, by testing, I can see that the tool's window should be shown when the tool itself is shown for it to remain on top as expected...that's strange, but that's what I observe.
Also, I noticed that Qt::X11BypassWindowManagerHint
messes things up...
Finally, by combining those observations + bnaecker reply, the code is:
#include <QtGui>
#include <QApplication>
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
// don't set Qt::X11BypassWindowManagerHint if you want the tool to stay on top!
QDialog* mw = new QDialog(0, Qt::WindowStaysOnTopHint);// | Qt::X11BypassWindowManagerHint);
mw->setWindowTitle(QLatin1String("Main"));
mw->resize(400, 300);
mw->move(100, 100);
// show main window before tool is shown
mw->show();
QWidget* d = new QWidget(mw, Qt::Tool);
d->setWindowTitle(QLatin1String("Tool"));
d->resize(200, 100);
d->show();
return app.exec();
}
Now, "Tool" window is on top of "Main" dialog and there's no way for it to be hidden by its parent.
Note that this work regardless if you specify or not Qt::WindowStaysOnTopHint
flag for the "Main" window. This flag has no effect on the fact that "Tool" remains on top of "Main". This makes "Main" (and so "Tool") be on top of any other application's window.
The problem is that you're calling QDialog::exec
, rather than directly about the window hints. The exec
method for a dialog shows it as a modal dialog, which means interaction with any other window in the application is not allowed until the user closes the dialog. Changing mw->exec()
into mw->show()
will demonstrate that the tool window can indeed be brought on top of the main window, regardless of the window hint.
You might consider using a main window that is not a QDialog
(which is an uncommon situation). Dialogs are intended to block the user from continuing with the normal use of the application until answering a question or acknowledging something (such as an error). They are not usually thought of as the main window through which a user interacts with an application. Using another subclass of QWidget
, such as QMainWindow
or even just a plain QWidget
with the Qt::Window
flag set, might be more appropriate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With