摘要:Qt布局管理的目標是將放置于窗體中的每一個部件都給定一個合適的位置和大小,常用的有QHBoxLayout水平布局管理器、QVBoxLayout垂直布局管理器、QgridLayout網(wǎng)格布局管理器。Qt程序員在完成窗體界面設(shè)計時,可通過可視化的方法搭建界面并布局;也可以純粹手工編寫C++源代碼來實現(xiàn)界面設(shè)計,編碼的方式更適合較復(fù)雜的布局。
關(guān)鍵詞:Qt布局管理;水平布局;垂直布局;網(wǎng)格布局;可視化方式;編碼方式
中圖分類號:TP311 文獻標識碼:A 文章編號:1009-3044(2014)25-5883-04
Qt是一個跨平臺的 C++圖形用戶界面庫,1991年由奇趣科技開發(fā)。2008年,奇趣科技被諾基亞公司收購,Qt也因此成為諾基亞旗下的編程語言工具,2012年8月Digia宣布對Qt業(yè)務(wù)及其技術(shù)全面收購。Qt技術(shù)的傳統(tǒng)優(yōu)勢都在桌面和嵌入式系統(tǒng),目前Digia將移動互聯(lián)網(wǎng)平臺定位為其主要的發(fā)展方向,很快將迎來Qt的移動時代。
Qt布局管理是設(shè)計應(yīng)用程序窗體界面時必須考慮的問題,它的目標是將放置于窗體中的每一個部件都給定一個合適的位置和大小,即使窗口尺寸大小被改變了,仍能就保證窗體上的部件始終擺放得美觀合適。Qt程序員有兩種途徑來完成窗體界面的設(shè)計和布局:第一種通過可視化的方法搭建界面,由菜單或工具欄中的布局管理器實現(xiàn)布局,可視化的方式比手工編碼更簡潔快速;第二種方式純粹手工編寫C++源代碼來實現(xiàn)界面設(shè)計,這種方式更適合較復(fù)雜的布局。
Qt提供了多個用于窗口布局的類,編寫界面代碼時可根據(jù)需求定義相應(yīng)的布局類對象。常用的有:QHBoxLayout、QVBoxLayout、QGridLayout三種,分別是水平布局管理器、垂直布局管理器、網(wǎng)格布局管理器。使用Qt布局管理器可以確保窗體能夠自動適應(yīng)于不同的字體、語言和系統(tǒng)平臺。
1 水平布局管理器和垂直布局管理器
QHBoxLayout,水平布局管理器,把窗口部件按照從左到右的順序排列布局;QVBoxLayout,垂直布局管理器,把窗口部件按照從上到下的順序排列布局。比如應(yīng)用程序需要創(chuàng)建一個登錄窗口,我們來看看界面設(shè)計方法。
1.1 可視化的方式
首先從窗口部件工具箱中拖拽控件圖標將其放到窗體中的大概位置,空白處可放入水平分隔符,這時分隔符會顯示為一個藍色的彈簧,但在最終結(jié)果的窗體中它是不可見的。然后按照功能需求在屬性編輯器中修改每一個窗口部件的屬性。此時的界面效果如圖1所示。
這時在窗體上出現(xiàn)的紅線是已創(chuàng)建的布局,但在窗體運行時,它們是不會出現(xiàn)的。
1.2 編碼實現(xiàn)方式
使用純粹編碼的方式來設(shè)計登錄窗體界面,首先要在登錄窗體的頭文件中聲明各個控件,再在其源文件的構(gòu)造函數(shù)中創(chuàng)建,布局也在構(gòu)造函數(shù)中實現(xiàn)。代碼如下:
loginDlg::loginDlg(QWidget *parent) :QDialog(parent)
{
setWindowTitle("Layout");
usernameLabel=new QLabel(tr("用戶名:")); //創(chuàng)建各個控件
usernameEdit=new QLineEdit();
passLabel=new QLabel(tr("密碼:"));
passEdit=new QLineEdit();
okButton=new QPushButton(tr("登錄"));
cancleButton=new QPushButton(tr("取消"));
QVBoxLayout *mainLayout=new QVBoxLayout(this); //整體為垂直布局
QHBoxLayout *firstLayout=new QHBoxLayout(this); //第一行的兩個控件水平排列
firstLayout→addWidget(usernameLabel);
firstLayout→addWidget(usernameEdit);
mainLayout→addLayout(firstLayout);
QHBoxLayout *secondLayout=new QHBoxLayout(this); //第二行的兩個控件水平排列
secondLayout→addWidget(passLabel);
secondLayout→addWidget(passEdit);
mainLayout→addLayout(secondLayout);
QHBoxLayout *thirdLayout=new QHBoxLayout(this); //第三行的兩個控件水平排列
thirdLayout→addWidget(okButton);
thirdLayout→addWidget(cancleButton);
mainLayout→addLayout(thirdLayout);
this→setLayout(mainLayout);
}
窗體運行時效果如圖4所示。在這種方式中,我們使用了3個水平布局管理器,1個垂直布局管理器,單純使用這兩種布局管理器的組合實現(xiàn)布局,雖然比較直觀,但代碼量也比較大。其實,我們還有另外一種更適合實現(xiàn)這種應(yīng)用程序窗體布局的方法:使用網(wǎng)格布局管理器QGridLayout。
圖4
2 網(wǎng)格布局管理器
QGridLayout,網(wǎng)格布局管理器,其含義就是將窗體分隔成行和列的網(wǎng)格來進行排列,將窗口部件整齊擺放,每個網(wǎng)格的單元格里放一個部件。如圖5所示。
類似上圖這種5行2列的布局比較容易實現(xiàn),只需要把各個部件填入到指定的單元格里即可。在可視化設(shè)計環(huán)境下把相應(yīng)窗口部件拖拽到窗口界面,然后由菜單或工具欄上的
gridLayout→addWidget(Label1, 0, 0); // 將Label1填到(0, 0)單元格
gridLayout→addWidget(LineEdit1, 0, 1); // 將LineEdit1填到(0, 1) 單元格
但是很多程序的窗體界面并不是一個規(guī)則的網(wǎng)格結(jié)構(gòu),這時網(wǎng)格布局管理器就顯示了它強大的靈活性,對于不規(guī)則排列的控件,可以看作跨行或跨列擺放,代碼表述為:
Layout→addWidget(widget, row, column, rowSpan, columnSpan );
其中,widget是要布局的窗口部件,(row, column )是該部件所占用的左上角單元格,rowSpan是該部件要占用的行數(shù),而columnSpan是該部件要占用的列數(shù)。rowSpan和columnSpan省略則默認為1。
舉例來說,比如圖6所示界面,第一行的兩個部件是比較規(guī)矩的處于兩個單元格內(nèi),但是第二行的QCheckBox部件就橫跨了兩列,即在水平方向上占用了兩個單元格,那么使用網(wǎng)格排列布局的代碼如下:
圖6
gridLayout→addWidget(QLabel, 0, 0); // QLabel在(0, 0)
gridLayout→addWidget(QLineEdit, 0, 1); // QLineEdit在(0, 1)
gridLayout→addWIdget(QCheckBox, 1, 0, 1, 2); // QCheckBox起始于(1, 0),縱向占1行,橫向跨2列
再比如圖7所示界面,QTreeWidget部件縱向跨越了三行(即在垂直方向上占用了這一列三個單元格),對應(yīng)的布局代碼:
圖7
gridLayout→addWidget(QTreeWidget, 0, 0, 3, 1); // QTreeWidget起始于(0, 0),并縱向跨3行,橫向占1列
gridLayout→addWidget(QPushButton1, 0, 1); // 第一個QPushButton在(0, 1)
gridLayout→addWIdget(QPushButton2, 1, 1); // 第二個QPushButton在(1, 1)
gridLayout→addWIdget(QPushButton3, 2, 1); // 第二個QPushButton在(2, 1)
下面來看一個網(wǎng)格布局編程實例。圖8所示界面是一個網(wǎng)絡(luò)聊天程序的客戶端窗口,由列表控件、行文本編輯器、標簽控件、按鈕等搭建而成,我們使用網(wǎng)格布局管理器來編程,對應(yīng)的構(gòu)造函數(shù)代碼:
圖8
TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f): QDialog(parent,f)
{setWindowTitle(tr("聊天室客戶端"));
contentListWidget = new QListWidget; //定義各窗口部件
sendLineEdit = new QLineEdit;
sendBtn = new QPushButton(tr("發(fā)送"));
userNameLabel = new QLabel(tr("用戶名:"));
userNameLineEdit = new QLineEdit;
serverIPLabel = new QLabel(tr("服務(wù)器地址:"));
serverIPLineEdit = new QLineEdit;
portLabel = new QLabel(tr("端口:"));
portLineEdit = new QLineEdit;
enterBtn = new QPushButton(tr("進入聊天室"));
QGridLayout *mainLayout = new QGridLayout(this); //定義網(wǎng)格布局管理器
mainLayout→addWidget(contentListWidget,0,0,1,2); //QListWidget橫向跨2列
mainLayout→addWidget(sendLineEdit,1,0); //各部件放入對應(yīng)單元格中
mainLayout→addWidget(sendBtn,1,1);
mainLayout→addWidget(userNameLabel,2,0);
mainLayout→addWidget(userNameLineEdit,2,1);
mainLayout→addWidget(serverIPLabel,3,0);
mainLayout→addWidget(serverIPLineEdit,3,1);
mainLayout→addWidget(portLabel,4,0);
mainLayout→addWidget(portLineEdit,4,1);
mainLayout→addWidget(enterBtn,5,0,1,2); //QPushButton橫向跨2列
}
3 結(jié)束語
本文所介紹的這三種布局管理器是Qt中最常用的布局管理器,在做界面布局的時候,可以使用網(wǎng)格布局管理器做整體框架設(shè)計,然后在其中包含一些水平或垂直布局管理器,或者他們的組合,即通過布局管理器的嵌套使用實現(xiàn)更復(fù)雜的界面效果。Qt中可以執(zhí)行布局管理功能的其他類還有QStackLayout、QSplitter、QScrollArea、QMdiArea等。
參考文獻:
[1] 閆鋒欣.C++ GUI Qt4編程[M]. 2版.北京: 電子工業(yè)出版社,2013.
[2] 鄭阿奇.Qt4 開發(fā)實踐[M].北京:電子工業(yè)出版社,2011.