概述
许多工程软件,如Qt Creator,VS,matlab等,都是使用dock布局窗口,这样用户可以自定义界面,自由组合窗口。
Qt的嵌套布局由QDockWidget完成,用Qt Creator拖界面得到的dock布置形式比较固定,不能得想要的任意组合形式,要得到如下图所示的效果,后续布局必须通过代码来完成。
ps:这是自己没事写的一个数据可视化软件
下面说说如何实现完全自由的界面布局效果:
QDockWidget在QMainWindow的布局函数
要在QMainWindow里对dock进行布局,需要用到如下几个函数:
添加dock函数
此函数用于给dock指定位置,同时也可以更改dock的位置,此函数命名为addDockWidget有点容易误导,因为不仅仅有add的功能,还有chang的功能
void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget)
void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget, Qt::Orientation orientation)
1
2
1
2
分割dock窗口函数
此函数的功能是把两个dock进行左右或上下并排布置,做成一个类似QSplit的功能
void QMainWindow::splitDockWidget(QDockWidget * first, QDockWidget * second, Qt::Orientation orientation)
1
1
tab化窗口函数
此函数的功能是把多个dock变成一个tab形式的窗体
void QMainWindow::tabifyDockWidget(QDockWidget * first, QDockWidget * second)
1
1
设置dock嵌套布局
此函数是设置嵌套布局的关键
void QMainWindow::setDockNestingEnabled(bool enabled)
1
1
以上几个函数就能完成比较复杂的嵌套布局了。
设置嵌套布局
下面通过例子来讲解如何设置复杂的嵌套布局
先用Qt Creator拖放9个dock进视图里,为了好区分,给每个dock设置一个背景颜色:
dock属性随便设置,保证都任意区域可以停靠即可
由于这里不需要MainWindow的中间窗口,整个视图都由dock组成,因此先把QMainWindow的中间窗口部件去除:
在MainWindow的构造函数加入如下语句,即可把MainWindow的中间窗口去除,这时整个MainWindow只有Dock组成
QWidget* p = takeCentralWidget();
if(p)
delete p;
1
2
3
1
2
3
编译出来的效果如图所示:
拖动dock可以发现,只能在两边进行组合,我想把dock放置到中间是无法实现的,这是由于为了简化dock的吸附,QMainWindow默认是把dock嵌套关闭的,需要我们手动设置,在MainWindow的构造函数里添加:
setDockNestingEnabled(true);
1
1
即可打开嵌套功能,这时编译出来的窗口能实现如下嵌套:
此时,整个窗口的布局将变得非常灵活且复杂,由于Qt Creator在ui编辑器中无法像编译出来的程序那样任意调整位置,因此需要手动对窗口进行设置。下面将介绍如何用代码设置复杂的dock
为了方便,添加两个函数和一个成员变量:
head:
public:
//移除并隐藏所有dock
void removeAllDock();
//显示dock窗口
void showDock(const QList& index = QList());
private:
QList m_docks;///< 记录所有dockWidget的指针
1
2
3
4
5
6
7
1
2
3
4
5
6
7
CPP:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//删除中央窗体
QWidget* p = takeCentralWidget();
if(p)
delete p;
//允许嵌套dock
setDockNestingEnabled(true);
//记录所有的dock指针
m_docks.append(ui->dockWidget_1);
m_docks.append(ui->dockWidget_2);
m_docks.append(ui->dockWidget_3);
m_docks.append(ui->dockWidget_4);
m_docks.append(ui->dockWidget_5);
m_docks.append(ui->dockWidget_6);
m_docks.append(ui->dockWidget_7);
m_docks.append(ui->dockWidget_8);
m_docks.append(ui->dockWidget_9);
}
MainWindow::~MainWindow()
{
delete ui;
}
///
/// \brief 移除并隐藏所有的dock
///
void MainWindow::removeAllDock()
{
for(int i=0;i<9;++i)
{
removeDockWidget(m_docks[i]);
}
}
///
/// \brief 显示指定序号的dock
/// \param index 指定序号,如果不指定,则会显示所有
///
void MainWindow::showDock(const QList &index)
{
if (index.isEmpty())
{
for(int i=0;i<9;++i)
{
m_docks[i]->show();
}
}
else
{
foreach (int i, index) {
m_docks[i]->show();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void removeAllDock();函数可以把所有的dock隐藏void showDock(const QList& index = QList())则可以显示指定的dock。
下面先对需要用到的几个函数进行示范:
addDockWidget
addDockWidget函数用于给MainWindow添加dock窗体,指定添加的区域,如果想改变dock的位置,也可以使用此函数进行移动。
void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget)
void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget, Qt::Orientation orientation)
1
2
1
2
如:
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
addDockWidget(Qt::RightDockWidgetArea,ui->dockWidget_2);
addDockWidget(Qt::TopDockWidgetArea,ui->dockWidget_3);
addDockWidget(Qt::BottomDockWidgetArea,ui->dockWidget_4);
1
2
3
4
1
2
3
4
把4个dock按照上下左右布置,效果如下:
splitDockWidget
splitDockWidget
void QMainWindow::splitDockWidget(QDockWidget * first, QDockWidget * second, Qt::Orientation orientation)
1
1
此函数可以把一个dock(QDockWidget * first)在其位置上进行嵌套,嵌套可以指定水平嵌套或者垂直嵌套,嵌套方向是从左到右,从上到下,也就是QDockWidget * first相对于QDockWidget * second永远在左边或者上边。
如:
removeAllDock();
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_4,Qt::Horizontal);
splitDockWidget(ui->dockWidget_4,ui->dockWidget_5,Qt::Horizontal);
showDock(QList()<< 0<<1<<2<<3<<4);
1
2
3
4
5
6
7
1
2
3
4
5
6
7
得到如下效果:
若是:
removeAllDock();
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Vertical);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Vertical);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_4,Qt::Vertical);
splitDockWidget(ui->dockWidget_4,ui->dockWidget_5,Qt::Vertical);
showDock(QList()<< 0<<1<<2<<3<<4);
1
2
3
4
5
6
7
1
2
3
4
5
6
7
那么效果变为:
此函数是实现嵌套布局的关键,首先指定基准,然后开始进行分割,即可得到比较复杂的布局。
分割原则是:先水平,再竖直,从左到右,从上到下
下面显示一个九宫格布局:
实现代码
removeAllDock();
//原则,先左右,再上下
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_4,Qt::Vertical);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_5,Qt::Vertical);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Vertical);
splitDockWidget(ui->dockWidget_4,ui->dockWidget_7,Qt::Vertical);
splitDockWidget(ui->dockWidget_5,ui->dockWidget_8,Qt::Vertical);
splitDockWidget(ui->dockWidget_6,ui->dockWidget_9,Qt::Vertical);
showDock();
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
实现代码:
removeAllDock();
//原则,先左右,再上下
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_4,Qt::Vertical);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Vertical);
splitDockWidget(ui->dockWidget_4,ui->dockWidget_7,Qt::Vertical);
splitDockWidget(ui->dockWidget_6,ui->dockWidget_9,Qt::Vertical);
showDock(QList()<< 0<<1<<2<<3<<5<<6<<8);
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
实现代码:
removeAllDock();
addDockWidget(Qt::TopDockWidgetArea,ui->dockWidget_1);
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_2);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_4,Qt::Horizontal);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_5,Qt::Horizontal);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Horizontal);
splitDockWidget(ui->dockWidget_4,ui->dockWidget_7,Qt::Horizontal);
showDock(QList()<< 0<<1<<2<<3<<4<<5<<6);
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
反正就是用splitDockWidget和addDockWidget你想怎么布置就怎么布置。
tabifyDockWidget
此函数就是实现tab合并功能
直接看看下面例子:
实现原理:
removeAllDock();
addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
splitDockWidget(ui->dockWidget_1,ui->dockWidget_4,Qt::Vertical);
splitDockWidget(ui->dockWidget_2,ui->dockWidget_5,Qt::Vertical);
splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Vertical);
tabifyDockWidget(ui->dockWidget_1,ui->dockWidget_7);
tabifyDockWidget(ui->dockWidget_5,ui->dockWidget_8);
tabifyDockWidget(ui->dockWidget_3,ui->dockWidget_9);
showDock();
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
代码:
本例代码下载:本例代码免积分-
http://blog.csdn.net/czyt1988/article/details/51209619#comments
NUint使用详解及Visual Studio配置
NUint使用详解及Visual Studio配置 阅读目录 什么是单元测试? 为什么使用单元测试? NUint使用详解: 示例 属性 断言 简单测试 VS配置: External Tools Vis ...
Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)
[Android布局学习系列] 1.Android 布局学习之——Layout(布局)详解一 2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数) 3.And ...
【单元测试】NUint使用详解及Visual Studio配置
阅读目录 什么是单元测试? 为什么使用单元测试? NUint使用详解: 示例 属性 断言 简单测试 VS配置: External Tools Visual Nunit 2010 NUnit Test ...
Android五大布局详解——FrameLayout(帧布局)
FrameLayout 这个布局相对前面两节介绍的布局就简单了很多,因此它的应用场景也就特别的少.这种布局没有方便的定位方式,所有的控件都会默认摆放在布局的左上角.新建UILayoutTestThre ...
Android五大布局详解——LinearLayout(线性布局)
Android五大布局 本篇开始介绍Android的五大布局的知识,一个丰富的界面显示总是要有众多的控件来组成的,那么怎样才能让这些控件能够按你的想法进行摆放,从而自定义你所想要的用户界面呢?这就牵涉 ...
详解在Visual Studio中使用git版本系统[转]
这篇教程的预期,是希望没有任何版本使用基础的新手也可以掌握,所以细节较多,不当之处,欢迎指正. 一 .安装 git 开发工具 如果要使用 git 进行版本管理,其实使用 git 命令行工具就完全足够了 ...
详解在visual studio中使用git版本系统(图文)
很多人已经在使用git(或正在转移到git上),在github.com上,也看到园子里不少同学的开源项目,非常不错.但相关教程似乎不多,所以趁着我自己的开源项目源码托管(https://github. ...
详解在Visual Studio中使用git版本系统
转自:http://www.uml.org.cn/pzgl/201206211.asp
【转】详解在visual studio中使用git版本系统(图文)
http://blog.csdn.net/wojilu/article/details/6976230 很多人已经在使用git(或正在转移到git上),在github.com上,也看到不少国内同学的开 ...
随机推荐
安卓SQLite常见错误
利用闲时写了一个简单的Sql语句操作SQLite数据库,在用SimpleCursorAdapter时出了一个异常好久都没解决 Process: com.example.chunchuner.usesq ...
Flatten Binary Tree to Linked List
Flatten a binary tree to a fake "linked list" in pre-order traversal. Here we use the righ ...
MSP430F149学习之路——LED
#include void int_clk(); void delay(int i); void main() { WDTCTL = WDTPW + WDTH ...
JS 获取Button控件的提交类型
windows下查找指定端口被哪个程序占用
在Windows环境下,用netstat命令查看某个端口号是否占用,为哪个进程所占用. eg.查看端口号为61078被哪个程序占用 1.查看端口号为61079被哪个PID所占用:Netstat –an ...
javascript实现小鸟飞行轨迹
javascript实现小鸟飞行轨迹 代码如下:
WPF在在设计模式,使用动态样式
1.问题分析 WPF有时候要用到主题样式,比如颜色主题(红色.黄色之类的)通常是key相同,而value不同,比如会这么写: Background="{DynamicResource Bac ...
LeetCode算法题-Non-decreasing Array(Java实现)
这是悦乐书的第283次更新,第300篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第151题(顺位题号是665).给定一个包含n个整数的数组,您的任务是通过修改最多1个元 ...
Ubuntu网络不通解决办法
如下问题: 尝试和Host主机互ping也不通, Ubuntu: vmware 桥接模式 IP:192.168.1.202/24 gateway:192.168.1.1 Host主机:网络正常 IP: ...
通过C#调用,实现js加密代码的反混淆,并运行js函数
前一篇我测试了vba调用htmlfile做反混淆,并执行js加密函数的代码.本文换成C#实现. 联系QQ:564955427 C#操作JS函数,可以通过ScriptControl组件,但这个组件只能在 ...