Qt «склеивает» два виджета вместе

У меня есть два виджета (оба QFrames), ни у одного из них нет связанной с ними строки заголовка (чего я достигаю через setWindowFlags(Qt::FramelessWindowHint)). Один из них является основным виджетом, а другой виджетом боковой панели, который должен прикрепляться к нему на правой границе (его высота составляет примерно 1/4 от основного виджета).

Я не могу держать их обоих в прозрачном QFrame со статическим позиционированием, так как основной виджет можно перетаскивать через его верхнюю часть (поскольку на нем отсутствует строка заголовка, я делаю это вручную, перехватывая события mousepress/mousemove и перемещая их соответственно). Пользовательское перетаскивание основного виджета работает нормально, но когда я пытаюсь переместить боковую панель вместе с ней, между ними появляется очень очевидная визуальная задержка, между ними видны мгновенные промежутки при перетаскивании основного виджета влево или мгновенное перекрытие между ними при перетаскивании основного виджета вправо (боковая панель не перетаскивается, для нее не реализована логика перетаскивания).

Как мне «склеить» эти два виджета вместе, чтобы они все время перемещались вместе без каких-либо задержек? Я просмотрел документы Qt, возможно, QDockWidget может помочь здесь, но я не мог понять, как это сделать. Главный виджет здесь не QMainWindow.

Платформа - OS X Yosemite, Qt 5.3.1, 32 бит.


person SexyBeast    schedule 03.01.2016    source источник


Ответы (1)


Вы обязательно должны использовать QDockWidget здесь.

Сделайте ваш «основной виджет» производным от QMainWindow, а не QFrame (это может быть неочевидным, поскольку QMainWindow не происходит от QFrame, но это не должно иметь большого значения).

Затем инкапсулируйте второй виджет в QDockWidget и закрепите его в основном виджете следующим образом:

// 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 );

Альтернативой является создание третьего виджета, который станет вашим виджетом верхнего уровня, и используйте QLayout для вставки ваших двух QFrame в этот новый:

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 );
person jpo38    schedule 03.01.2016
comment
Спасибо. Отнимет ли это QMainWindow какой-либо атрибут, который я мог бы сделать с QFrame, например, удаление строки заголовка, возможность перетаскивания, несмотря на это, использование только изображения в качестве фона с использованием свойства полупрозрачного фона и т. д.? А как приклеить сайдбар? Будет ли добавление виджета дока через addDockWidget автоматически склеивать их? Разве первый параметр не должен быть RightDockingArea, учитывая, что основной виджет находится слева, а боковая панель — справа от него? - person SexyBeast; 03.01.2016
comment
Да, попробуйте RightDockingArea, вы увидите, как это будет выглядеть, когда они будут склеены. Но пользователь по-прежнему может открепить виджет. С альтернативным решением, которое я предлагаю, пользователь не может отклеить виджеты. - person jpo38; 03.01.2016
comment
Но, как я сказал во втором абзаце, это решение неосуществимо, так как мне нужно сделать основной виджет подвижным, а вместе с ним и боковую панель. Как этого добиться, поместив их в родительский виджет? И как пользователь может их отстыковать? Я буду удалять кнопки отмены/закрытия через setWindowFlags(Qt::FramelessWindowHint). Как тогда пользователь отстыкует боковую панель? - person SexyBeast; 03.01.2016
comment
Поместив их внутрь родительского виджета, они склеятся вместе и будут перемещаться вместе при перемещении родителя. Это самый простой способ сделать так, чтобы два виджета оставались рядом друг с другом. - person jpo38; 03.01.2016