zoukankan      html  css  js  c++  java
  • Qt QDockWidget嵌套布局详解-实现Visual Studio布局

    #概述
    许多工程软件,如Qt Creator,VS,matlab等,都是使用dock布局窗口,这样用户可以自定义界面,自由组合窗口。
    Qt的嵌套布局由QDockWidget完成,用Qt Creator拖界面得到的dock布置形式比较固定,不能得想要的任意组合形式,要得到如下图所示的效果,后续布局必须通过代码来完成。

    这里写图片描述

    ps:这是自己没事写的一个数据可视化软件
    下面说说如何实现完全自由的界面布局效果:
    #QDockWidget在QMainWindow的布局函数
    要在QMainWindow里对dock进行布局,需要用到如下几个函数:

    添加dock函数
    此函数用于给dock指定位置,同时也可以更改dock的位置,此函数命名为addDockWidget有点容易误导,因为不仅仅有add的功能,还有chang的功能

    1 void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget)
    2 void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget, Qt::Orientation orientation)

    分割dock窗口函数
    此函数的功能是把两个dock进行左右或上下并排布置,做成一个类似QSplit的功能

    void QMainWindow::splitDockWidget(QDockWidget * first, QDockWidget * second, Qt::Orientation orientation)

    tab化窗口函数
    此函数的功能是把多个dock变成一个tab形式的窗体

    void QMainWindow::tabifyDockWidget(QDockWidget * first, QDockWidget * second)

    设置dock嵌套布局
    此函数是设置嵌套布局的关键

    void QMainWindow::setDockNestingEnabled(bool enabled)

    以上几个函数就能完成比较复杂的嵌套布局了。
    #设置嵌套布局
    下面通过例子来讲解如何设置复杂的嵌套布局
    先用Qt Creator拖放9个dock进视图里,为了好区分,给每个dock设置一个背景颜色:

    dock属性随便设置,保证都任意区域可以停靠即可
    由于这里不需要MainWindow的中间窗口,整个视图都由dock组成,因此先把QMainWindow的中间窗口部件去除:
    在MainWindow的构造函数加入如下语句,即可把MainWindow的中间窗口去除,这时整个MainWindow只有Dock组成

    1 QWidget* p = takeCentralWidget();
    2     if(p)
    3         delete p;

    编译出来的效果如图所示:
    这里写图片描述

    拖动dock可以发现,只能在两边进行组合,我想把dock放置到中间是无法实现的,这是由于为了简化dock的吸附,QMainWindow默认是把dock嵌套关闭的,需要我们手动设置,在MainWindow的构造函数里添加:

    setDockNestingEnabled(true);

    即可打开嵌套功能,这时编译出来的窗口能实现如下嵌套:
    这里写图片描述

    此时,整个窗口的布局将变得非常灵活且复杂,由于Qt Creator在ui编辑器中无法像编译出来的程序那样任意调整位置,因此需要手动对窗口进行设置。下面将介绍如何用代码设置复杂的dock
    为了方便,添加两个函数和一个成员变量:
    head:

    1 public:
    2     //移除并隐藏所有dock
    3     void removeAllDock();
    4     //显示dock窗口
    5     void showDock(const QList<int>& index = QList<int>());
    6 private:
    7     QList<QDockWidget*> m_docks;///< 记录所有dockWidget的指针

    CPP:

     1 MainWindow::MainWindow(QWidget *parent) :
     2     QMainWindow(parent),
     3     ui(new Ui::MainWindow)
     4 {
     5     ui->setupUi(this);
     6     //删除中央窗体
     7     QWidget* p = takeCentralWidget();
     8     if(p)
     9         delete p;
    10     //允许嵌套dock
    11     setDockNestingEnabled(true);
    12     //记录所有的dock指针
    13     m_docks.append(ui->dockWidget_1);
    14     m_docks.append(ui->dockWidget_2);
    15     m_docks.append(ui->dockWidget_3);
    16     m_docks.append(ui->dockWidget_4);
    17     m_docks.append(ui->dockWidget_5);
    18     m_docks.append(ui->dockWidget_6);
    19     m_docks.append(ui->dockWidget_7);
    20     m_docks.append(ui->dockWidget_8);
    21     m_docks.append(ui->dockWidget_9);
    22 }
    23 
    24 MainWindow::~MainWindow()
    25 {
    26     delete ui;
    27 }
    28 ///
    29 /// rief 移除并隐藏所有的dock
    30 ///
    31 void MainWindow::removeAllDock()
    32 {
    33     for(int i=0;i<9;++i)
    34     {
    35         removeDockWidget(m_docks[i]);
    36     }
    37 }
    38 ///
    39 /// rief 显示指定序号的dock
    40 /// param index 指定序号,如果不指定,则会显示所有
    41 ///
    42 void MainWindow::showDock(const QList<int> &index)
    43 {
    44     if (index.isEmpty())
    45     {
    46         for(int i=0;i<9;++i)
    47         {
    48             m_docks[i]->show();
    49         }
    50     }
    51     else
    52     {
    53         foreach (int i, index) {
    54             m_docks[i]->show();
    55         }
    56     }
    57 }

    void removeAllDock();函数可以把所有的dock隐藏void showDock(const QList<int>& index = QList<int>())则可以显示指定的dock。
    下面先对需要用到的几个函数进行示范:
    ##addDockWidget
    addDockWidget函数用于给MainWindow添加dock窗体,指定添加的区域,如果想改变dock的位置,也可以使用此函数进行移动。

    1 void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget)
    2 void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget, Qt::Orientation orientation)

    如:

    1 addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
    2 addDockWidget(Qt::RightDockWidgetArea,ui->dockWidget_2);
    3 addDockWidget(Qt::TopDockWidgetArea,ui->dockWidget_3);
    4 addDockWidget(Qt::BottomDockWidgetArea,ui->dockWidget_4);

    把4个dock按照上下左右布置,效果如下:
    这里写图片描述

    ##splitDockWidget
    splitDockWidget

    void QMainWindow::splitDockWidget(QDockWidget * first, QDockWidget * second, Qt::Orientation orientation)

    此函数可以把一个dock(QDockWidget * first)在其位置上进行嵌套,嵌套可以指定水平嵌套或者垂直嵌套,嵌套方向是从左到右,从上到下,也就是QDockWidget * first相对于QDockWidget * second永远在左边或者上边。
    如:

    1 removeAllDock();
    2 addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
    3 splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
    4 splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
    5 splitDockWidget(ui->dockWidget_3,ui->dockWidget_4,Qt::Horizontal);
    6 splitDockWidget(ui->dockWidget_4,ui->dockWidget_5,Qt::Horizontal);
    7 showDock(QList<int>()<< 0<<1<<2<<3<<4);

    得到如下效果:

     若是:

    1 removeAllDock();
    2 addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
    3 splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Vertical);
    4 splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Vertical);
    5 splitDockWidget(ui->dockWidget_3,ui->dockWidget_4,Qt::Vertical);
    6 splitDockWidget(ui->dockWidget_4,ui->dockWidget_5,Qt::Vertical);
    7 showDock(QList<int>()<< 0<<1<<2<<3<<4);

    那么效果变为:
    这里写图片描述

    此函数是实现嵌套布局的关键,首先指定基准,然后开始进行分割,即可得到比较复杂的布局。
    分割原则是:先水平,再竖直,从左到右,从上到下
    下面显示一个九宫格布局:
    这里写图片描述

    实现代码

     1 removeAllDock();
     2 //原则,先左右,再上下
     3 addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
     4 splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
     5 splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
     6 splitDockWidget(ui->dockWidget_1,ui->dockWidget_4,Qt::Vertical);
     7 splitDockWidget(ui->dockWidget_2,ui->dockWidget_5,Qt::Vertical);
     8 splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Vertical);
     9 splitDockWidget(ui->dockWidget_4,ui->dockWidget_7,Qt::Vertical);
    10 splitDockWidget(ui->dockWidget_5,ui->dockWidget_8,Qt::Vertical);
    11 splitDockWidget(ui->dockWidget_6,ui->dockWidget_9,Qt::Vertical);
    12 showDock();

     

    实现代码:

     1 removeAllDock();
     2 //原则,先左右,再上下
     3 addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
     4 splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
     5 splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
     6 splitDockWidget(ui->dockWidget_1,ui->dockWidget_4,Qt::Vertical);
     7 splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Vertical);
     8 splitDockWidget(ui->dockWidget_4,ui->dockWidget_7,Qt::Vertical);
     9 splitDockWidget(ui->dockWidget_6,ui->dockWidget_9,Qt::Vertical);
    10 showDock(QList<int>()<< 0<<1<<2<<3<<5<<6<<8);

    这里写图片描述
    实现代码:

    1 removeAllDock();
    2 addDockWidget(Qt::TopDockWidgetArea,ui->dockWidget_1);
    3 addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_2);
    4 splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
    5 splitDockWidget(ui->dockWidget_3,ui->dockWidget_4,Qt::Horizontal);
    6 splitDockWidget(ui->dockWidget_2,ui->dockWidget_5,Qt::Horizontal);
    7 splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Horizontal);
    8 splitDockWidget(ui->dockWidget_4,ui->dockWidget_7,Qt::Horizontal);
    9 showDock(QList<int>()<< 0<<1<<2<<3<<4<<5<<6);

    反正就是用splitDockWidgetaddDockWidget你想怎么布置就怎么布置。
    ##tabifyDockWidget
    此函数就是实现tab合并功能
    直接看看下面例子:
    这里写图片描述

    实现原理:

     1 removeAllDock();
     2 addDockWidget(Qt::LeftDockWidgetArea,ui->dockWidget_1);
     3 splitDockWidget(ui->dockWidget_1,ui->dockWidget_2,Qt::Horizontal);
     4 splitDockWidget(ui->dockWidget_2,ui->dockWidget_3,Qt::Horizontal);
     5 splitDockWidget(ui->dockWidget_1,ui->dockWidget_4,Qt::Vertical);
     6 splitDockWidget(ui->dockWidget_2,ui->dockWidget_5,Qt::Vertical);
     7 splitDockWidget(ui->dockWidget_3,ui->dockWidget_6,Qt::Vertical);
     8 tabifyDockWidget(ui->dockWidget_1,ui->dockWidget_7);
     9 tabifyDockWidget(ui->dockWidget_5,ui->dockWidget_8);
    10 tabifyDockWidget(ui->dockWidget_3,ui->dockWidget_9);
    11 showDock();
  • 相关阅读:
    20180925-5代码规范
    20180925-4 单元测试,结对
    20180925-6 四则运算试题生成
    20180925-3 效能分析
    20170925-2 功能测试
    20180925-7 规格说明书——吉林市两日游
    20180918-1 词频统计
    第二周例行报告
    iOS开发-CocoaPods使用详细说明
    svn的使用详解
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14577183.html
Copyright © 2011-2022 走看看