How to let QDockWidget behind QMainwindow
rogo last edited by
I have a question. Our application uses QDockWidgets to display, among others, console like log output. It is nice to be able to undock the log, move it to a secondary monitor and make some space for editing a file. However, because the QDockWidget always stays on top it sometimes blocks the rest of the application visually. Our users asked us to change this behavior, as most would expect the widget to be able to be put to the background by clicking in the main window.
To achieve this behavior we listen to dockTopLevelChanged events and change the windowFlags of the undocked widget from Qt::Tool to Qt::Window. This works well on Linux and macOS where the undocked widgets gets an operating system specific window border and appears in the taskbar, so users could easily find their undocked widget and bring it back to the foreground. On Windows however, this does not work as expected; The widget always stays on top of the mainwindow.
It says somewhere in the documentation that a child widget cannot be put behind its parent by design (on windows at least). But changing the parent of the widget when being undocked only crashes the application.
Is there any way to circumvent this behavior and allow undocked QDockWidgets to be put behind the QMainWindow?
We also tried "transferring" the widget inside the QDockWidget to a newly spawned QMainWindow (or QWidget) but that breaks the drag and drop behavior that users use to dock/undock the dockwidget as even when hiding the original dockwidget, there is still an invisible dockwidget at the mouse cursor until the user releases the left mouse button. This invisible dockwidget is still able to be put into a docking area, leading to confusing behavior.
Any help is greatly appreciated.
Hi and welcome to devnet,
What about the stay on top/back hints ? Would that work for you ?
rogo last edited by
Hello and thank you for your quick reply.
I tested this and unfortunalety this did not solve the problem. It is an interesting idea though.
Setting the stayAtBottom hint is something we actually tried already. This leads to the mainwindow staying even further in the back than the undocked widget. So the rule child-not-infront-of-parent stays active for that case.
So what i did try now was setting the stayOnTop hint whenever the mainwindow gets activated and removing it whenever it gets deactivated. this actually enables the child to be put behind its parent!
In order to make this (partly) work i had to install an event filter for all undocked widgets because the windowActivate event is relayed from the dockwidget to the mainwindow apparently. So without the filter, everytime a user clicks on the undocked widget, the mainwindow would pop up back again over the child that should be in the foreground.
So far, so good. All of this breaks however when trying to remove the stayOnTop flag from the mainwindow. The removal needs to happen everytime the focus of the mainwindow is lost. So i remove the WindowStayOnTopHint and afterwards have to call show() because windows disappear when changing window flags. The problem is that show() then again triggers the WindowActivate event, re-enabling the stayontop hint. This can be filtered but when i do this i end up with a situation where - for some reason - i need to click an undocked widget twice, once to put it to the foreground and a second time to actually activate the widget window.
I am sure that this is a problem in my code and/or can be worked around but this solution starts to be getting dirtier and more hacky. So before diving further down that rabbit hole i would like to double check if there is a more straight forward solution the the actual problem. I also the fear side effects of setting the mainwindow to stay on top, especially if there is a thrid party application window (file explorer or whatever) involved that the user would expect to be "in between" my application windows (a user clicks on myMainwindow, file explorer, myUndockedWidget in that order type-of-situation).
Thanks for reading all of this