赞
踩
QDockWidget是一个可以停靠在QMainWindow内的窗口控件,它可以保持浮动状态或在指定位置作为子窗口附加到主窗口中。停靠窗口QDockWidget类是应用程序中经常用到的,设置停靠窗口的一般流程如下。
这里使用Qt Designer ,随意拖拽添加QDockWidget到MainWindow任意区域可以停靠即可,在代码中对QDockWidget进行管理。Qt Designer无法任意调整位置,可以使用代码初始化QDockWidget布局。
setFeatures()方法设置停靠窗体的特性,参数QDockWidget::DockWidgetFeatures指定停靠窗体的特性,包括以下几种参数。
① QDockWidget::DockWidgetClosable:停靠窗体可关闭。
② QDockWidget::DockWidgetMovable:停靠窗体可移动。
③ QDockWidget::DockWidgetFloatable:停靠窗体可浮动。
④ QDockWidget::AllDockWidgetFeatures:此参数表示拥有停靠窗体的所有特性。
⑤ QDockWidget::NoDockWidgetFeatures:不可移动、不可关闭、不可浮动。
setAllowedAreas()方法设置停靠窗体可停靠的区域,参数Qt::DockWidgetAreas指定了停靠窗体可停靠的区域,包括以下几种参数。
① Qt::LeftDockWidgetArea:可在主窗口的左侧停靠。
② Qt::RightDockWidgetArea:可在主窗口的右侧停靠。
③ Qt::TopDockWidgetArea:可在主窗口的顶端停靠。
④ Qt::BottomDockWidgetArea:可在主窗口的底部停靠。
⑤ Qt::AllDockWidgetArea:可在主窗口任意(以上四个)部位停靠。
⑥ Qt::NoDockWidgetArea:只可停靠在插入处。
addDockWidget()方法用于添加dock,给dock指定位置,同时也可以更改dock的位置。
void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget)
splitDockWidget()方法用于分割dock窗口,是把两个dock进行左右或上下并排布置,做成一个类似QSplit的功能,分割原则是:水平从左到右,竖直从上到下。
void QMainWindow::splitDockWidget(QDockWidget * first, QDockWidget * second, Qt::Orientation orientation)
tabifyDockWidget()方法用于tab化窗口,把多个dock变成一个tab形式的窗体。
void QMainWindow::tabifyDockWidget(QDockWidget * first, QDockWidget * second)
靠左右布局的QDockWidget的高度是自适应的,宽度需要初始化设置,同理靠上下布局的高度需要初始化设置。使用splitDockWidget分割、tabifyDockWidget tab化窗口的QDockWidget的初始化大小与其依赖的QDockWidget(参数first)初始化大小一样。
void QMainWindow::resizeDocks(const QList<QDockWidget *> &docks, const QList<int> &sizes, Qt::Orientation orientation)
它的第一个参数是用来配置是哪个dock窗口需要调整大小;第二个参数是用来配置dock所占的像素大小,如果配置大于或者小于QMainWindow本身空间,Qt会根据所配置的像素大小的相对权重分配到dock中;第三个参数用来配置调整的方向,如果为Qt::Horizontal,调整dock宽度,Qt::Vertical调整dock高度,确定了停靠位置后resizeDocks才起作用。需要注意的是Qt官方文档上有注明这个方法在Qt5.6中引入,所以比Qt5.6低的版本并不能使用本方法。resizeDocks在多行或多列时初始化高宽无效问题!
使用setFeatures、setAllowedAreas、addDockWidget、splitDockWidget、tabifyDockWidget、resizeDocks可以满足基本的Dock布局了。
去掉标题栏,但是不能拖动了。
QWidget *Widget = new QWidget;
ui->dockwidget_dockWidget_1->setTitleBarWidget(Widget);
自定义QWidget即可以自定义标题栏。
ui->dockwidget_dockWidget_6->setFeatures(QDockWidget::DockWidgetVerticalTitleBar);
当使用tabifyDockWidgets进行tab化窗口时对Tabbar设置背景色时发现Tabbar上方有一行间隙。在QSS中使用qproperty-drawBase: 0;可以使得背景色填充到间隙中,但是发现Tabbar超过两个后其他的Tabbar不生效!!!
QTabBar {
qproperty-drawBase: 0;
background: rgb(45, 45, 45);
}
直接在代码中遍历Tabbar设置DrawBase属性可以解决Tabbar上方有一行间隙无法填充背景色问题。
Q_FOREACH (QTabBar *bar, this->findChildren<QTabBar *>())
{
bar->setDrawBase(false);
}
当tab个数大于一定个数时,会出现如下图左侧白线所示,这个是Qt自带的,作用是点击回到第一个tab,但是显示不好看,这里隐藏掉
QTabBar::tear {
width: 0px;
border: none;
}
#include "dockwidget.h" #include <QtCore/QtCore> DockWidget::DockWidget(QWidget *parent) : QMainWindow(parent), ui(new Ui_dockwidget) { ui->setupUi(this); StyleMgr::SetStyleToWidgetByCssFile(this, ":/helloqt/resources/qss/custom/dockwidget.qss"); // 如果不需要MainWindow的中间窗口,整个视图都由QDockWidget组成,可以把QMainWindow的中间窗口部件去除 // QWidget *p = takeCentralWidget(); // if (p) // delete p; // 当不需要MainWindow的中间窗口时,发现不能拖动QDockWidget到中间,需要设置 // setDockNestingEnabled(true); ui->dockwidget_dockWidget_1->setWindowTitle("Dock 1"); ui->dockwidget_dockWidget_2->setWindowTitle("Dock 2"); ui->dockwidget_dockWidget_3->setWindowTitle("Dock 3"); ui->dockwidget_dockWidget_4->setWindowTitle("Dock 4"); ui->dockwidget_dockWidget_5->setWindowTitle("Dock 5"); ui->dockwidget_dockWidget_6->setWindowTitle("Dock 6"); ui->dockwidget_dockWidget_7->setWindowTitle("Dock 7"); ui->dockwidget_dockWidget_8->setWindowTitle("Dock 8"); ui->dockwidget_dockWidget_9->setWindowTitle("Dock 9"); ui->dockwidget_dockWidget_1->setFeatures(QDockWidget::DockWidgetMovable); //可移动 ui->dockwidget_dockWidget_2->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); //可关闭、移动 ui->dockwidget_dockWidget_3->setFeatures(QDockWidget::DockWidgetMovable); //可移动 ui->dockwidget_dockWidget_4->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); //可关闭、移动 ui->dockwidget_dockWidget_5->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); //可关闭、移动 ui->dockwidget_dockWidget_6->setFeatures(QDockWidget::DockWidgetMovable); //可移动 ui->dockwidget_dockWidget_7->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); //可关闭、移动 ui->dockwidget_dockWidget_8->setFeatures(QDockWidget::DockWidgetMovable); //可移动 ui->dockwidget_dockWidget_9->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); //可关闭、移动 ui->dockwidget_dockWidget_1->setAllowedAreas(Qt::TopDockWidgetArea); //可在主窗口的上侧停靠。 ui->dockwidget_dockWidget_3->setAllowedAreas(Qt::LeftDockWidgetArea); //可在主窗口的左侧停靠。 ui->dockwidget_dockWidget_6->setAllowedAreas(Qt::RightDockWidgetArea); //可在主窗口的右侧停靠。 ui->dockwidget_dockWidget_8->setAllowedAreas(Qt::BottomDockWidgetArea); //可在主窗口的下侧停靠。 // 去掉标题栏 // QWidget *Widget = new QWidget; // ui->dockwidget_dockWidget_1->setTitleBarWidget(Widget); // 把QDockWidget标题栏竖起来 // ui->dockwidget_dockWidget_6->setFeatures(QDockWidget::DockWidgetVerticalTitleBar); m_docks.append(ui->dockwidget_dockWidget_1); m_docks.append(ui->dockwidget_dockWidget_2); m_docks.append(ui->dockwidget_dockWidget_3); m_docks.append(ui->dockwidget_dockWidget_4); m_docks.append(ui->dockwidget_dockWidget_5); m_docks.append(ui->dockwidget_dockWidget_6); m_docks.append(ui->dockwidget_dockWidget_7); m_docks.append(ui->dockwidget_dockWidget_8); m_docks.append(ui->dockwidget_dockWidget_9); } DockWidget::~DockWidget() { delete ui; } void DockWidget::ShowDockLayout(int type) { RemoveAllDock(); switch (type) { case 1: addDockWidget(Qt::TopDockWidgetArea, ui->dockwidget_dockWidget_1); addDockWidget(Qt::LeftDockWidgetArea, ui->dockwidget_dockWidget_3); addDockWidget(Qt::RightDockWidgetArea, ui->dockwidget_dockWidget_6); addDockWidget(Qt::BottomDockWidgetArea, ui->dockwidget_dockWidget_8); resizeDocks({ui->dockwidget_dockWidget_1, ui->dockwidget_dockWidget_8}, {200, 100}, Qt::Vertical); //上下 resizeDocks({ui->dockwidget_dockWidget_3, ui->dockwidget_dockWidget_6}, {300, 300}, Qt::Horizontal); //左右 ShowDock(QList<int>() << 0 << 2 << 5 << 7); break; case 2: addDockWidget(Qt::TopDockWidgetArea, ui->dockwidget_dockWidget_1); addDockWidget(Qt::LeftDockWidgetArea, ui->dockwidget_dockWidget_3); addDockWidget(Qt::RightDockWidgetArea, ui->dockwidget_dockWidget_6); addDockWidget(Qt::BottomDockWidgetArea, ui->dockwidget_dockWidget_8); resizeDocks({ui->dockwidget_dockWidget_1, ui->dockwidget_dockWidget_8}, {200, 100}, Qt::Vertical); //上下,初始化高度 resizeDocks({ui->dockwidget_dockWidget_3, ui->dockwidget_dockWidget_6}, {300, 300}, Qt::Horizontal); //左右,初始化宽度 resizeDocks({ui->dockwidget_dockWidget_1}, {200}, Qt::Horizontal); splitDockWidget(ui->dockwidget_dockWidget_1, ui->dockwidget_dockWidget_2, Qt::Horizontal); resizeDocks({ui->dockwidget_dockWidget_3}, {50}, Qt::Vertical); splitDockWidget(ui->dockwidget_dockWidget_3, ui->dockwidget_dockWidget_4, Qt::Vertical); resizeDocks({ui->dockwidget_dockWidget_4}, {100}, Qt::Vertical); splitDockWidget(ui->dockwidget_dockWidget_4, ui->dockwidget_dockWidget_5, Qt::Vertical); resizeDocks({ui->dockwidget_dockWidget_6}, {150}, Qt::Vertical); splitDockWidget(ui->dockwidget_dockWidget_6, ui->dockwidget_dockWidget_7, Qt::Vertical); resizeDocks({ui->dockwidget_dockWidget_8}, {300}, Qt::Horizontal); splitDockWidget(ui->dockwidget_dockWidget_8, ui->dockwidget_dockWidget_9, Qt::Horizontal); ShowDock(QList<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8); break; case 3: addDockWidget(Qt::TopDockWidgetArea, ui->dockwidget_dockWidget_1); tabifyDockWidget(ui->dockwidget_dockWidget_1, ui->dockwidget_dockWidget_2); addDockWidget(Qt::LeftDockWidgetArea, ui->dockwidget_dockWidget_3); tabifyDockWidget(ui->dockwidget_dockWidget_3, ui->dockwidget_dockWidget_4); tabifyDockWidget(ui->dockwidget_dockWidget_4, ui->dockwidget_dockWidget_5); addDockWidget(Qt::RightDockWidgetArea, ui->dockwidget_dockWidget_6); tabifyDockWidget(ui->dockwidget_dockWidget_6, ui->dockwidget_dockWidget_7); addDockWidget(Qt::BottomDockWidgetArea, ui->dockwidget_dockWidget_8); tabifyDockWidget(ui->dockwidget_dockWidget_8, ui->dockwidget_dockWidget_9); resizeDocks({ui->dockwidget_dockWidget_1, ui->dockwidget_dockWidget_8}, {200, 100}, Qt::Vertical); //上下 resizeDocks({ui->dockwidget_dockWidget_3, ui->dockwidget_dockWidget_6}, {300, 300}, Qt::Horizontal); //左右 ShowDock(QList<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8); break; default: break; } // 解决Tabbar上方有一行间隙无法填充背景色问题 Q_FOREACH (QTabBar *bar, this->findChildren<QTabBar *>()) { bar->setDrawBase(false); } } /// @brief 移除并隐藏所有的dock void DockWidget::RemoveAllDock() { for (int i = 0; i < 9; ++i) { removeDockWidget(m_docks[i]); } } /// @brief 显示指定序号的dock /// @param index 指定序号,如果不指定,则会显示所有 void DockWidget::ShowDock(const QList<int> &index) { if (index.isEmpty()) { for (int i = 0; i < 9; ++i) { m_docks[i]->show(); } } else { foreach (int i, index) { m_docks[i]->show(); } } }
QWidget#dockwidget { border: none; background-color: rgb(30, 30, 30); } QDockWidget#dockwidget_dockWidget_1, #dockwidget_dockWidgetContents_1 { border: none; background-color: rgb(189, 79, 60); } QDockWidget#dockwidget_dockWidget_2, #dockwidget_dockWidgetContents_2 { border: none; background-color: rgb(189, 133, 60); } QDockWidget#dockwidget_dockWidget_3, #dockwidget_dockWidgetContents_3 { border: none; background-color: rgb(161, 189, 60); } QDockWidget#dockwidget_dockWidget_4, #dockwidget_dockWidgetContents_4 { border: none; background-color: rgb(60, 189, 109); } QDockWidget#dockwidget_dockWidget_5, #dockwidget_dockWidgetContents_5 { border: none; background-color: rgb(60, 152, 189); } QDockWidget#dockwidget_dockWidget_6, #dockwidget_dockWidgetContents_6 { border: none; background-color: rgb(62, 60, 189); } QDockWidget#dockwidget_dockWidget_7, #dockwidget_dockWidgetContents_7 { border: none; background-color: rgb(105, 60, 189); } QDockWidget#dockwidget_dockWidget_8, #dockwidget_dockWidgetContents_8 { border: none; background-color: rgb(178, 60, 189); } QDockWidget#dockwidget_dockWidget_9, #dockwidget_dockWidgetContents_9 { border: none; background-color: rgb(189, 60, 120); } /* QDockWidget之间的间距调整 */ QMainWindow::separator { width: 0px; height: 0px; margin: 0px; /* 如果将两个QDockWidget之间的间距调为0后,QDockWidget将没办法拉拽,所以留出一点小缝隙 */ padding: 0, 1px; } QDockWidget { color: white; } /* 标题设置 */ QDockWidget::title { /* 标题字体在这里设置无效,要在QDockWidget中设置! */ /* color: white; */ text-align: left; /* 不设置背景色时标题栏下方有空隙! */ background: rgb(45, 45, 48); padding-left: 5px; } /* 按钮图标 */ QDockWidget { border: 1px solid rgb(45, 45, 48); titlebar-close-icon: url(:/dockwidget/resources/image/dockwidget/close.png); titlebar-normal-icon: url(:/dockwidget/resources/image/dockwidget/normal.png); } QDockWidget::close-button, QDockWidget::float-button { /* 不设置border则hover、pressed时的background颜色不生效! */ border: 1px solid transparent; background: rgb(45, 45, 48); /* 会影响标题栏高度 */ /* padding: 0px; */ /* 不起作用! */ icon-size: 32px; } QDockWidget::close-button:hover, QDockWidget::float-button:hover { color: rgb(0, 151, 251); background: rgb(62, 62, 64); } QDockWidget::close-button:pressed, QDockWidget::float-button:pressed { background: rgb(37, 37, 38); padding: 1px -1px -1px 1px; } /* tabifyDockWidgets TabBar设置*/ QTabBar { qproperty-drawBase: 0; background: rgb(45, 45, 48); } QTabBar::tab { color: white; background: rgb(45, 45, 48); padding: 4px; border: 1px solid transparent; } QTabBar::tab:hover { color: rgb(0, 151, 251); } QTabBar::tab:selected { color: rgb(0, 151, 251); background: rgb(37, 37, 38); border-bottom-color: rgb(0, 151, 251); } /* 当tab个数大于一定个数时,会出现如下图左侧白线所示,这个是Qt自带的,作用是点击回到第一个tab,但是显示不好看,这里隐藏掉 */ QTabBar::tear { width: 0px; border: none; }
https://github.com/weichangk/helloqt
https://doc.qt.io/qt-5/qdockwidget.html
https://doc.qt.io/qt-5/qmainwindow.html#resizeDocks
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qdockwidget
https://github.com/czyt1988/czyBlog/tree/master/tech/QDockWidget_VSStudioMode
https://zhuanlan.zhihu.com/p/381444869
https://forum.qt.io/topic/88409/stylesheet-and-qtabbar-which-element-is-this
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。