1. 程式人生 > 其它 >Qt - 佈局管理器

Qt - 佈局管理器

佈局管理組(Layouts)

什麼是佈局管理器?你一個窗口裡面一般有很多widgets對吧,你如果要自己調它們的位置,大小的話會比較麻煩,而且當視窗變大的時候它裡面的widgets又不會跟著變大,就很煩惱。所以,我們有這個東西,佈局管理器,相當於一個小管家,你只要把widgets丟進去,他自己會幫你排好它的。

方法:

首先,建立好我們想要佈局的widgets。

然後,我們建立 QBoxLayout 物件並將小部件新增到佈局中。

最後,我們呼叫 QWidget::setLayout() 將 QBoxLayout 物件安裝到小部件上。

此時,佈局中的小部件將重新設定父物件,為上面呼叫setLayout()的視窗。

1,盒子佈局(BoxLayout)

QBoxLayout可以在水平方向或垂直方向上排列控制元件,分別派生了QHBoxLayout、QVBoxLayout子類。

QHBoxLayout:水平佈局,在水平方向上排列控制元件,即:左右排列。 QVBoxLayout:垂直佈局,在垂直方向上排列控制元件,即:上下排列。

水平佈局、垂直佈局除了構造時的方向(LeftToRight、TopToBottom)不同外,其它均相同。

公有函式
序號 函式&描述
1 void addLayout(QLayout* layout,int stretch = 0) 將layout新增到框的末端,使用連續拉伸因子拉伸。 
2 void addSpacerItem(QSpacerItem * spacerItem) 將spaceeritem新增到該盒子佈局的末尾,通常不使用這個函式,請使用addSpacing(int size)
3 void addSpacing(int size) 新增一個大小為size的不可伸縮空間(QSpacerItem)到這個框佈局的末尾
4 void addStretch(int stretch = 0) 新增一個可伸縮空間(一個QSpacerItem),最小尺寸為零,拉伸因子stretch到這個框佈局的末尾。 
5 void addStrut(int size) 限制盒子的垂直尺寸最小為size
6 void addWidget(QWidget* widget,int stretch = 0,Qt::Alignment alignment = 0) 將小部件新增到此框佈局的末尾,並使用拉伸因子拉伸和對齊對齊。
7 void setDirection(QBoxLayout::Direction direction) 設定此佈局的方向為direction。 
8 void setSpacing(int spacing) 設定小部件之間的間距 
9 void setStretch(int index,int stretch) 給index位置的控制元件設定拉伸因子stretch
10 bool setStretchFactor(QWidget* widget,int stretch) bool setStretchFactor(QWidget* widget,int stretch) 設定小部件的拉伸因子,如果在佈局中發現小部件(不包括子佈局),則返回true; 否則返回false。

下面我們以QHBoxLayout為例,來講解QBoxLayout的常用功能。

  • 簡單佈局

//建立需要佈局的小部件
QLabel* nameLabel = new QLabel("name");
QLineEdit* nameEdit = new QLineEdit;
//建立佈局
QBoxLayout* hlayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight);
//把小部件新增到佈局
hlayout->addWidget(nameLabel);
hlayout->addWidget(nameEdit);
//給當前視窗設定佈局
this->setLayout(hlayout);

  • 佈局巢狀

//姓名                         
QLabel* nameLabel = new QLabel("Name");
QLineEdit* nameEdit = new QLineEdit;
​
QBoxLayout* nameHlayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight);     
nameHlayout->addWidget(nameLabel);
nameHlayout->addWidget(nameEdit);
//電話
QLabel* phoneLabel = new QLabel("Phone");
QLineEdit* phoneEdit = new QLineEdit;
​
QBoxLayout* phoneHlayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight);    
phoneHlayout->addWidget(phoneLabel);
phoneHlayout->addWidget(phoneEdit);
//佈局巢狀
QBoxLayout* mainlayout = new QBoxLayout(QBoxLayout::Direction::TopToBottom);      
mainlayout->addLayout(nameHlayout);
mainlayout->addLayout(phoneHlayout);
this->setLayout(mainlayout);

基本使用
  • 建立五個按鈕,新增到水平佈局

QPushButton *btn1 = new QPushButton("One");
QPushButton *btn2 = new QPushButton("Two");
QPushButton *btn3 = new QPushButton("Three");
QPushButton *btn4 = new QPushButton("Four");
QPushButton *btn5 = new QPushButton("Five");
​
QHBoxLayout* hlayout = new QHBoxLayout;
hlayout->addWidget(btn1);
hlayout->addWidget(btn2);
hlayout->addWidget(btn3);
hlayout->addWidget(btn4);
hlayout->addWidget(btn5);
​
this->setLayout(hlayout);

 

  • 設定邊距

void setMargin(int margin);
void setContentsMargins(int left,int top,int right,int bottom);

這裡我使用setMargin(0)將外邊距設定為0。

  • 設定間距

void setSpacing(int spacing)

 

  • 新增拉伸空間(QSpacerItem)

QHBoxLayout* hlayout = new QHBoxLayout;
hlayout->addStretch();      //新增拉伸空間
hlayout->addWidget(btn1);
...

 

在第一個控制元件之前新增伸縮,這樣所有的控制元件就會居右顯示。

在最後一個控制元件之後新增伸縮,這樣所有的控制元件就會居左顯示。

在第一個控制元件之前,最後一個空間之後新增伸縮,這樣所有的控制元件就會居中顯示。

  • 新增控制元件addWidget

void addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = 0)

預設是居中對齊的,我們把其中一個按鈕的高度設定大一點,就可以看到非常明顯了~

 

下面,我們使用向上、向下對齊來設定其它控制元件。

QHBoxLayout* hlayout = new QHBoxLayout;
hlayout->addStretch();      //新增拉伸空間
hlayout->addWidget(btn1,0,Qt::AlignmentFlag::AlignTop);
hlayout->addWidget(btn2,0,Qt::AlignmentFlag::AlignTop);
hlayout->addWidget(btn3,0);
hlayout->addWidget(btn4,0,Qt::AlignmentFlag::AlignBottom);
hlayout->addWidget(btn5,0,Qt::AlignmentFlag::AlignBottom);

 

  • 設定佈局方向

void setDirection(QBoxLayout::Direction direction)
//可以設定從左到右、從右到左、從上到下、從下到上等。。。

setDirection(QBoxLayout::RightToLeft)

setDirection(QBoxLayout::TopToBottom);

既然使用了QHBoxLayout,一般就不建議使用TopToBottom或者BottomToTop,如果實在確定不了方向,或者方向可以隨意變化,那麼建議使用QBoxLayout。

設定拉伸係數

當窗體大小變化時,控制元件會根據拉伸係數來做相應的調整。

//設定小部件的拉伸因子,如果在佈局中發現小部件(不包括子佈局),則返回true; 否則返回false。  
bool setStretchFactor(QWidget *widget, int stretch)
bool setStretchFactor(QLayout *layout, int stretch)
    
hlayout->setStretchFactor(btn2,1);
hlayout->setStretchFactor(btn3,2);    

 

設定btn2的拉伸係數為1,btn3拉伸係數為2,當窗體變大時,會優先將btn3進行拉伸,當達到一定程度時,再拉伸btn2,btn2與btn3的寬度比例為1:2。

2,網格佈局(GridLayout)

網格佈局也叫格柵佈局(多行多列)

QGridLayout佔用它可用的空間(通過它的父佈局或parentWidget()),將它分成行和列,並將它管理的每個小部件放入正確的單元格中。

列和行表現相同; 我們將討論列,但行也有等價的函式。

每一列都有一個最小寬度和一個拉伸因子。 最小寬度是使用setColumnMinimumWidth()設定的最大寬度和該列中每個小部件的最小寬度。 拉伸因子使用setColumnStretch()設定,並確定列將獲得的可用空間超過或超過必要的最小空間的多少。

公有函式
序號 函式&描述
2 void addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment = 0) void addLayout(QLayout *layout, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = 0) 將layout放置在網格中的位置(row、column)。 左上角的位置是(0,0)。 跨越多行/多列。 該單元格將從跨rowSpan行和columnSpan列的行、列開始。
3 void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = 0) void addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0) 同上
4 void setRowStretch(int row, int stretch) 將row的拉伸因子設定為stretch
5 void setColumnStretch(int column, int stretch) 將column的拉伸因子設定為stretch
6 voidsetRowMinimumHeight(int row, int minSize) 將行的最小寬度設定為minSize畫素。 
7 voidsetColumnMinimumWidth(int column, int minSize) 將列的最小寬度設定為minSize畫素。 

 

QLabel* imageLabel = new QLabel;                         
QLineEdit* userNamaeEdit = new QLineEdit;                
QLineEdit* passwdEdit = new QLineEdit;                   
QCheckBox* rememberCheckBox = new QCheckBox;             
QCheckBox* autoLoginCheckBox = new QCheckBox;            
QPushButton* registerBtn = new QPushButton;              
QPushButton* forgetBtn = new QPushButton;                
QPushButton* loginBtn = new QPushButton;                 
                                                         
//設定圖片                                                   
imageLabel->setFixedSize(90,90);                         
imageLabel->setPixmap(QPixmap("://images/loginIcon.png"));
imageLabel->setScaledContents(true);                     
                                                         
//設定輸入框                                                  
userNamaeEdit->setPlaceholderText("QQ號碼/手機/郵箱");         
passwdEdit->setPlaceholderText("密碼");                    
                                                         
//設定複選框                                                  
rememberCheckBox->setText("記住密碼");                       
autoLoginCheckBox->setText("自動登入");                      
                                                         
//設定按鈕                                                   
registerBtn->setText("註冊賬號");                            
forgetBtn->setText("找回密碼");                              
loginBtn->setText("登入");                                 
                                                         
QGridLayout* layout = new QGridLayout;                   
layout->addWidget(imageLabel,0,0,3,1);                   
layout->addWidget(userNamaeEdit,0,1,1,2);                
layout->addWidget(registerBtn,0,3);                      
layout->addWidget(passwdEdit,1,1,1,2);                   
layout->addWidget(forgetBtn,1,3);                        
layout->addWidget(rememberCheckBox,2,1);                 
layout->addWidget(autoLoginCheckBox,2,2);                
layout->addWidget(loginBtn,3,1,1,2);                     
                                                         
layout->setHorizontalSpacing(10);                        
layout->setVerticalSpacing(10);                          
layout->setContentsMargins(20,20,20,20);                 
                                                         
this->setLayout(layout);                                 

 

3,表單佈局(FormLayout)

QFormLayout類管理輸入小部件的表單及其關聯的標籤

QFormLayout 是一個方便的佈局類,它以兩列形式佈置其子項。 左列由標籤組成,右列由“欄位”小部件(行編輯器、旋轉框等)組成。 傳統上,這種兩列表單佈局是使用 QGridLayout 實現的。

QFormLayout 是一種更高級別的替代方案,具有以下優點:

  • 遵守不同平臺的外觀和感覺準則 例如,macOS Aqua 和 KDE 指南指定標籤應該右對齊,而 Windows 和 GNOME 應用程式通常使用左對齊。

  • 支援長行換行

    對於顯示較小的裝置,QFormLayout可以設定為對長行進行換行,甚至對所有行進行換行。

  • 建立標籤-欄位對,有非常方便的API 我們可以通過addRow(const QString &labelText, QWidget *field)來建立一個帶有給定文字的QLabel及QWidget控制元件行,它們可以自動的設定為夥伴關係。

公有函式
序號 函式&描述
1 void addRow(QWidget* label,QWidget* field) void addRow(QWidget* label,QLayout* field) 使用給定的label和field在此表單佈局的底部新增新行
2 void addRow(const QString &labelText, QWidget* field) void addRow(const QString &labelText, QLayout* field) 這個過載會在後臺自動建立一個以labelText作為文字的QLabel。 field被設定為新的QLabel的夥伴
3 void addRow(QWidget *widget) void addRow(QLayout* layout) 在表單佈局的末尾新增指定的小部件。 這個小部件橫跨兩列
9 void setRowWrapPolicy(QFormLayout::RowWrapPolicy policy) true
10 void setSpacing(int spacing) 將垂直和水平間距設定為spacing。
11 void setVerticalSpacing(int spacing) 將垂直間距設定為spacing
12 void setWidget(int row, QFormLayout::ItemRole role, QWidget *widget) 將給定的row中的role設定為widget,必要時使用空行擴展布局。 如果單元格已被佔用,則不插入小部件,並將錯誤訊息傳送到控制檯。
QLineEdit* userEdit = new QLineEdit;
QLineEdit* passwdEdit = new QLineEdit;
QPushButton* loginBtn = new QPushButton("確定");
​
QFormLayout* fromLayout = new QFormLayout;
fromLayout->addRow("userName:",userEdit);
fromLayout->addRow("password:",passwdEdit);
fromLayout->addWidget(loginBtn);
​
this->setLayout(fromLayout);

將其與下面使用QGridLayout編寫的程式碼進行比較:

QLineEdit* userEdit = new QLineEdit;
QLineEdit* passwdEdit = new QLineEdit;
QPushButton* loginBtn = new QPushButton("確定");
​
QLabel*userLabel = new QLabel("userName:");
QLabel*passwdLabel = new QLabel("passwdEdit:");
​
QGridLayout* glayout = new QGridLayout;
glayout->addWidget(userLabel,0,0);
glayout->addWidget(userEdit,0,1);
glayout->addWidget(passwdLabel,1,0);
glayout->addWidget(passwdEdit,1,1);
glayout->addWidget(loginBtn,2,1);
​
this->setLayout(glayout);
  • 設定換行策略 void setRowWrapPolicy(QFormLayout::RowWrapPolicy policy)

    列舉 描述 效果
    QFormLayout::DontWrapRows 欄位總是放在它們的標籤旁邊(預設樣式)
    QFormLayout::WrapLongRows 標籤有足夠的空間適應,如果欄位對的最小大小大於可用空間,輸入框會被換到下一行
    QFormLayout::WrapAllRows 欄位總是在它們的標籤下面。
  • 設定控制元件 void setWidget(int row, QFormLayout::ItemRole role, QWidget *widget)

    • 將給定角色的給定行中的小部件設定為widget,必要時使用空行擴展布局。

內容 描述
QFormLayout::LabelRole 0 標籤
QFormLayout::FieldRole 1 欄位
QFormLayout::SpanningRole 2 跨標籤和欄位列的小部件
QFormLayout * flayout = new QFormLayout;
flayout->setWidget(0,QFormLayout::ItemRole::LabelRole,new QLabel("LabelRole"));
flayout->setWidget(0,QFormLayout::ItemRole::FieldRole,new QLineEdit("FieldRole"));
flayout->setWidget(1,QFormLayout::ItemRole::SpanningRole,new QPushButton("SpanningRole"));
​
this->setLayout(flayout);

 

4,堆疊佈局(StackedLayout)

QStackedLayout繼承自QLayout。

QStackedLayout類提供了多頁面切換的佈局,一次只能看到一個介面。

QStackedLayout可用於建立類似於QTabWidget提供的使用者介面。也有建立在QStackedLayout之上的便利類QStackedWidget

sngnals

//每當佈局中的當前小部件發生變化時,都會發出此訊號。 index指定新的當前小部件的索引,如果沒有新的小部件,則-1
void currentChanged(int index)      
//每當從佈局中刪除小部件時,都會發出此訊號,inded是刪除的索引。    
void widgetRemoved(int index)

slots

void setCurrentIndex(int index)
void setCurrentWidget(QWidget *widget)

 

公有函式

序號 函式&描述
2 int addWidget(QWidget *widget) 把widget新增到佈局中
5 int insertWidget(int index, QWidget *widget) 把widget插入到指定的下標
6 void setStackingMode(QStackedLayout::StackingMode stackingMode) 設定子小部件可見性的處理方式。 

5,分割器(Splitter)

QSplitter類實現了一個分離小部件。 splitter允許使用者通過拖動子部件之間的邊界來控制它們的大小。 任何數量的小部件都可以由單個拆分器控制。QSplitter的典型用法是建立幾個小部件並使用 insertWidget()或addWidget()新增它們。

QSplitter *splitter = new QSplitter(this);
splitter->addWidget(new QTextBrowser);
splitter->addWidget(new QTextBrowser);
splitter->addWidget(new QTextBrowser);
​
splitter->setHandleWidth(2);
splitter->setCollapsible(0,false);
​
​
QSplitter *sp = new QSplitter(Qt::Orientation::Vertical,splitter);
sp->addWidget(new QTextBrowser);
sp->addWidget(new QTextBrowser);

搜尋

複製