Search code examples
c++qtqwidgetqdockwidgetqlayout

Qt 'glue' two widgets together


I have two widgets (both QFrames), none of them have any title bar associated with them (which I achieve through setWindowFlags(Qt::FramelessWindowHint)). One of them is a main widget, and the other a sidebar sort of widget, which is supposed to stick to it at its right boundary (its height being approximately 1/4th of the main widget).

I cannot keep them both in a transparent QFrame with static positioning, since the main widget is draggable through its top (since title bar is missing on it, I do it manually by intercepting mousepress/mousemove events and moving it accordingly). The custom drag on the main widget works fine, but when I try to move the sidebar along with, a very obvious visual delay shows up between the two, there are momentary gaps visible between the two while dragging the main widget to the left, or momentary overlapping between the two when dragging the main widget to the right (the sidebar is not draggable, no drag logic is implemented for it).

How do I 'glue' these two widgets together, such that they move together all the time without any delay? I browsed the Qt docs, it may be possible that QDockWidget can help here, but I could not understand how. The main widget here is not a QMainWindow.

Platform - OS X Yosemite, Qt 5.3.1, 32 bit.


Solution

  • You should definitely use QDockWidget here.

    Make your "main widget" derive from QMainWindow rather than QFrame (it may not be "obvious" as QMainWindow does not derive from QFrame, but it should not be such a big deal).

    Then, encapsulate your second widget within a QDockWidget and dock it in the main widget like that:

    // secondWidget being your QFrame based widget
    // mainWidget being your "main widget"
    QDockWidget* dockingBar = new QDockWidget("My bar", mainWidget );
    dockingBar->setWidget( secondWidget );
    // dock on left side, change first parameter to dock somewhere else:
    mainWidget->addDockWidget( Qt::LeftDockWidgetArea, dockingBar );
    

    An alternative is to create a third widget that would become your top-level widget and use a QLayout to insert your two QFrames in this new one:

    QWidget* newTopLevelWidget = new QWidget();
    // QHBoxLayout to have mainWidget on the left hand side of secondWidget
    // Replace by QVBoxLayout to have mainWidget on top of secondWidget
    QLayout* layout = new QHBoxLayout( newTopLevelWidget );
    layout->addWidget( mainWidget );
    layout->addWidget( secondWidget );