QDockWidget嵌套布局詳解-實現QT Creator布局


概述

許多工程軟件,如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<int>& index = QList<int>()); private: QList<QDockWidget*> 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<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(); } } } 
  • 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<int>& index = QList<int>())則可以顯示指定的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<int>()<< 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<int>()<< 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<int>()<< 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<int>()<< 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

反正就是用splitDockWidgetaddDockWidget你想怎么布置就怎么布置。

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

本文來源於:https://www.cnblogs.com/findumars/p/5436533.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM