Перетаскиваемые вкладки QDockWidget
Я использую QDockWidgets и размещаю два из них в левой части моего приложения, чтобы вкладки можно было использовать для выбора между ними. Однако поведение по умолчанию Qt для этого выглядит ужасно и неинтуитивно. Вместо того, чтобы перетаскивать вкладки для перемещения виджетов, она помещает другую панель под выбранной вкладкой (с тем же именем), которую нужно перетащить. Как пользователь, было бы трудно понять это.
![enter image description here]()
(Мои QDockWidgets - это "Атрибуты" и "Библиотека" )
Есть ли способ избавиться от этого второго бара и сделать так, чтобы я мог перемещать свои QDockWidgets, перетаскивая сами вкладки?
Ответы
Ответ 1
Если вы добавляете QTabWidgets
в главное окно, полученное из QMainWindow
, вы можете попробовать tabifyDockWidget
.
Он отображает два QDockWidgets
так, как вы хотели, и, конечно же, вы можете их перетащить.
dockWidget1 = new QDockWidget("Tab1") ;
dockWidget2 = new QDockWidget("Tab2") ;
this->addDockWidget(Qt::LeftDockWidgetArea , dockWidget1 );
this->addDockWidget(Qt::LeftDockWidgetArea , dockWidget2 );
this->tabifyDockWidget(dockWidget1,dockWidget2);
Ответ 2
Я думаю, Том не был слишком далеко от решения:
Вы можете настроить свой собственный виджет как строку заголовка:
myDockingWidget->setTitleBarWidget(myTitleBar)
Если вы создаете этот виджет, чтобы не показывать заголовок окна док-станции, у вас его есть. Через сигнал QDockWidget::topLevelChanged
ваш док-виджет может даже стать информированным, когда он станет плавающим, поэтому вы можете снова включить заголовок в myTitleBar
.
Ответ 3
Насколько я понимаю из QDockWidget::mousePressEvent
реализации в src/gui/widgets/qdockwidget.cpp
, перетаскивание dockwidgets с помощью вкладок возможно NOT:
QDockWidgetLayout *dwLayout
= qobject_cast<QDockWidgetLayout*>(layout);
if (!dwLayout->nativeWindowDeco()) {
QRect titleArea = dwLayout->titleArea();
if (event->button() != Qt::LeftButton ||
!titleArea.contains(event->pos()) ||
// check if the tool window is movable... do nothing if it
// is not (but allow moving if the window is floating)
(!hasFeature(this, QDockWidget::DockWidgetMovable) && !q->isFloating()) ||
qobject_cast<QMainWindow*>(parent) == 0 ||
isAnimating() || state != 0) {
return false;
}
initDrag(event->pos(), false);
....
Как видно из реализации, одна из вещей, которые проверяет проверка QDockWidget
перед тем, как разрешить расстыковку, - это то, что событие нажатия мыши появилось из строки заголовка или нет.
Ответ 4
Вы пробовали:
myDockingWidget->setTitleBarWidget(0)
изменить
QWidget* titleWidget = new QWidget(this);
mUi.dockWidget->setTitleBarWidget(titleWidget);
где 'this' - QMainWindow
это приведет к удалению строки заголовка, хотя я не уверен, как сделать QDockWidget перетаскиваемым из вкладок
Ответ 5
Похоже, вы установили, что позиция вкладки док-станции находится сверху. По умолчанию это будет внизу. Затем это не так визуально, чтобы иметь текст вкладки прямо рядом с текстом строки заголовка.
Я не думаю, что есть способ сделать то, что вы предлагаете в Qt (исключить строку заголовка QDockWidget
и перетащить с вкладки), по крайней мере, не со стандартными виджетами. Вероятно, вы могли бы написать много настраиваемого кода, чтобы это произошло, но это, вероятно, не стоит.
Вместо этого я предлагаю перемещать вкладки в нижнюю часть (см. QMainWindow::setTabPosition
) или, возможно, одну из сторон.
Ответ 6
Я также считаю, что setTitleBarWidget()
действительно делает трюк. Я помню, что он использовался для аналогичной цели в исходном коде музыкальный плеер Amarok. У Amarok есть QMainWindow, который содержит только виджеты док-станции. Возможно, вы захотите посмотреть исходный код.