Resizing docked widgets without stretching others
-
I have a complex application with a main window, one or more docked windows (on the left), a zero-sized central widget, and another docked widget on the right. The one or more widgets on the left are usually configured as vertical (top to bottom) widgets, similar to the project widget in Qt Creator. The widget on the right contains another main window object and displays various types of data views in tabbed windows. Everything can be undocked and positioned on the screen, or docked into their allowed locations. This all works fine.
These docked widgets on the left are added to mainwindow using addDockWidget() (for the first one) and if there is more than one of them, using splitDockWidget(). There is always one specific widget that is the first one in the dock--other widgets may come and go per user requests.
Now the problem: when there are two or more of these vertical widgets on the left, resizing becomes a game of whack-a-mole. Per the design of Qt docking scheme, they will stretch relative to each other. This makes my app very much less friendly, since these widgets each have long trees of configuration data, etc., and making one larger (say to be able to better see a longer data element) makes others smaller, then obscuring other information that users often need to see at the same time.
What I would prefer to happen is that resizing one widget (by grabbing the splitter on the left of the one to resize) only changes the size of that widget, and the others slide left or right as needed, maintaining their current size. The screen area that can be sacrificed in this operation is the widget on the right.
I have tried all sorts of ways to make this happen, but nothing that really works right. I can programmatically lock the size of a particular widget by setting minimum size and maximum size to the current size. This almost works, but not all of the splitters will move properly in this case. For example, leaving the left-most widget alone and setting min/max to size() for the others in the split dock means that none of the splitters will move except the rightmost one. Then the "locked" size widgets move, keeping their size, and the leftmost widget is resized. The interaction should rather be to grab the slider immediately to the right of the leftmost widget (in this case) and move it, with the other widgets maintaining their size and moving as a group. Again, the widget on the far right (the one containing another mainwindow) is the sacrificial one--with it either gaining or losing size as the other widgets are resized.
I'm able to detect mouse presses on the various splitters (they fall through to the underlying mainwindow, as it turns out, so a filter works to capture them), and I can tell which widget is meant to be resized. But I cannot seem to make things work the way I want.
Any ideas on how to do this? While I understand that Qt wants things to be done a certain way, it's default behavior isn't always the best user interface in all cases.
Related question: the Qt framework doesn't seem to be very consistent, or at least what's exposed in the API isn't. For example, it would seem logical that split dock widgets would be implemented under the hood using QSplitter, but there doesn't seem to be any way to get access to such an object. It acts a bit as if there is one implementation of splitters for the mainwindow split docks and another one for QSplitter-containing widgets. There are many other cases I've run across where one class has functionality that another similar class does not. Why is this?
Thanks for any help,
Paul
-
Hi and welcome to devnet,
It sounds like you need your own specialised layout to achieve what you want.
While I understand that Qt wants things to be done a certain way, it's default behavior isn't always the best user interface in all cases.
Qt doesn't want to do thing a certain way, it follows as close a possible the UI and UI guidelines of the platform it runs on. It can't cover each and every use case. Yours for example I haven't encountered yet in any application. And I must say I would be surprised if resizing one widget would push another in the same window outside my screen.
Related question: the Qt framework doesn't seem to be very consistent, or at least what's exposed in the API isn't. For example, it would seem logical that split dock widgets would be implemented under the hood using QSplitter, but there doesn't seem to be any way to get access to such an object. It acts a bit as if there is one implementation of splitters for the mainwindow split docks and another one for QSplitter-containing widgets. There are many other cases I've run across where one class has functionality that another similar class does not. Why is this?
QMainWindow's main features are made available through a dedicated layout that offers consistent UI across platforms. If you take the QSplitter case, it wouldn't match what you see in native UIs on these platforms with regard to dock widget handling.
What other cases do you have in mind ?
-
@SGaist Thanks for chiming in, but unfortunately an answer along the lines of "your desire is not valid" doesn't really help solve the problem. I suppose I could spend time trying to search for some program that does use more than one pane side by side and doesn't resize all of them when one is resized, but that doesn't really help me solve my technical problem either. It's not that interesting to debate the merits of one design over another...we all have work to get done.
Is it possible for someone to respond regarding the technical aspects of solving this, rather than reflexively defend the paradigm that Qt uses as if it was the only thing in existence? I'm just trying to move forward with this seemingly simple interaction.
Thanks!
-
@SGaist said in Resizing docked widgets without stretching others:
It sounds like you need your own specialised layout to achieve what you want.
https://doc.qt.io/qt-5/layout.html#how-to-write-a-custom-layout-manager
-
@brent-avermetrics said in Resizing docked widgets without stretching others:
@SGaist Thanks for chiming in, but unfortunately an answer along the lines of "your desire is not valid" doesn't really help solve the problem. I suppose I could spend time trying to search for some program that does use more than one pane side by side and doesn't resize all of them when one is resized, but that doesn't really help me solve my technical problem either. It's not that interesting to debate the merits of one design over another...we all have work to get done.
At no point did I imply that your desire wasn't valid.
Is it possible for someone to respond regarding the technical aspects of solving this, rather than reflexively defend the paradigm that Qt uses as if it was the only thing in existence? I'm just trying to move forward with this seemingly simple interaction.
Thanks!
The very first line after my greeting was a suggestion for you to go further.
If my explanation about why your use case is not as easy to implement as you expected is perceived as reflexive defense then I'll stop here.
Good luck
-
So I'm circling back on this issue--I've been off implementing other features since I wasn't making any progress on this.
Sorry if we got off on the wrong foot. Certain things in Qt that would seem to be easy are sometimes hard to understand, and this particular area is one, at least for me, and I was really frustrated at the time. Not to excuse my tone...that was my mistake.
There is an example that does something like what I'm after: QT Linguist. I'm not sure how it's implemented there, but the effect is similar to what I am looking for. In particular, the on the right side there are three horizontal panes: one with two docks ("Strings" and "Sources and Forms"), one with source text and translation text, and one at the bottom with two docks ("Phrases and guesses" and "Warnings").
If you grab the splitter between the bottom and middle docks and move, the bottom dock will resize, and the other two stay the same. So, if the bottom dock grows in size it is at the expense of the middle one. Likewise, if the bottom dock is dragged smaller (down) the middle dock gets larger.
The exact same thing happens with the splitter between the middle dock and the one at the top. This is what I need to do, except that in my case all the docks are vertical and the splitters move left and right instead of up and down.
I've spend some time looking at the source for QMainWindow and QDockWindow (and related) but nothing has jumped out at me to point me in a good direction. I've also looked at a custom layout manager, but that's not clear to me how that gets me there. It seems there is a layout manager in the main window (QDockAreaLayout) that might be handling this, so it's not clear to me how I would create and use a replacement, if that is what is suggested.
Does anyone have an idea how QLinguist is doing this? It feels like it shouldn't be that hard, but I can't see how to do it yet.
-
@brent-avermetrics said in Resizing docked widgets without stretching others:
Does anyone have an idea how QLinguist is doing this? It feels like it shouldn't be that hard, but I can't see how to do it yet.
I don't, but you'll find the answer you seek in the Qt Linguist source code: https://code.qt.io/cgit/qt/qttools.git/tree/src/linguist
-
@JKSH said in Resizing docked widgets without stretching others:
I don't, but you'll find the answer you seek in the Qt Linguist source code: https://code.qt.io/cgit/qt/qttools.git/tree/src/linguist
Yes, I just found that source and have been going through it. Sadly, this doesn't seem to hold any secrets: the splitters are working this way because this is a standard QMainWindow with a central widget ("Source text..."), and other dock widgets arranged around them.
What I really need is similar behavior with one or more dock widgets in a splitDockWidget on one side of the app, and another dock on the right, with no visible central widget. I have all of this working great, except that I don't want all the dock widgets to resize in proportion when one of them is resized. Only the one to be resized should change and the others in the split dock stay the same size. (The dock on the right side should grow and shrink as the split dock is resized.)