4.4 基本布局(QLayout)
Qt提供了QHBoxLayout类、QVBoxLayout类及QGridLayout类等的基本布局管理,分别是水平排列布局、垂直排列布局和网格排列布局。它们之间的继承关系如图4.6所示。
图4.6 各种布局类及之间的关系
布局中常用的方法有addWidget()和addLayout ()。
addWidget()方法用来向布局中加入需布局的控件,addWidget()的函数原型如下:
void addWidget ( QWidget *widget, //为需插入的控件对象 int fromRow, //为插入的行 int fromColumn, //为插入的列 int rowSpan, //表示占用的行数 int columnSpan, //表示占用的列数 Qt::Alignment alignment=0 //描述各控件的对齐方式 )
addLayout ()方法用来向布局中加入需布局的子布局,addLayout ()的函数原型如下:
void addLayout ( QLayout *layout, //表示要插入的子布局对象 int row, //插入的起始行 int column, //插入的起始列 int rowSpan, //表示占用的行数 int columnSpan, //表示占用的列数 Qt::Alignment alignment=0 //指定对齐方式 )
其中各个参数的作用如注释所示。
本小节将通过实现一个“用户基本资料修改”的功能来介绍如何使用基本布局管理,如QHBoxLayout类、QVBoxLayout类及QGridLayout类,效果如图4.7所示。本实例共用到4个布局管理器,分别是LeftLayout、RightLayout、BottomLayout和MainLayout,其布局框架如图4.8所示。见代码CH404。
图4.7 基本信息实例
图4.8 基本信息实例布局框架
本实例是采用编写代码的方式实现的,具体实现步骤如下:
(1) 创建一个工程,在创建过程中,创建过程中在“Qt4 Gui Application”界面中,选择“Base Class”下拉列表框中“QDialog”选项,取消“Gernerate form”复选框的选中状态。
(2) 打开“dialog.h”头文件,在头文件中声明对话框中的各个控件。添加如下代码:
class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); private: //左侧 QLabel *UserNameLabel; QLabel *NameLabel; QLabel *SexLabel; QLabel *DepartmentLabel; QLabel *AgeLabel; QLabel *OtherLabel; QLineEdit *UserNameLineEdit; QLineEdit *NameLineEdit; QComboBox *SexComboBox; QTextEdit *DepartmentTextEdit; QLineEdit *AgeLineEdit; QGridLayout *LeftLayout; //右侧 QLabel *HeadLabel; //右上角部分 QLabel *HeadIconLabel; QPushButton *UpdateHeadBtn; QHBoxLayout *TopRightLayout; QLabel *IntroductionLabel; //右下角部分 QTextEdit *IntroductionTextEdit; QVBoxLayout *RightLayout; //底部 QPushButton *OkBtn; QPushButton *CancelBtn; QHBoxLayout *ButtomLayout; }; 接着添加如下的头文件: #include <QLabel> #include <QLineEdit> #include <QComboBox> #include <QTextEdit> #include <QGridLayout>
(3) 打开“dialog.cpp”文件,在类Dialog的构造函数中添加如下代码:
Dialog::Dialog(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("UserInfo")); /************** 左侧 ******************************/ UserNameLabel =new QLabel(tr("用户名:")); UserNameLineEdit =new QLineEdit; NameLabel =new QLabel(tr("姓名:")); NameLineEdit =new QLineEdit; SexLabel =new QLabel(tr("性别:")); SexComboBox =new QComboBox; SexComboBox->addItem(tr("女")); SexComboBox->addItem(tr("男")); DepartmentLabel =new QLabel(tr("部门:")); DepartmentTextEdit =new QTextEdit; AgeLabel =new QLabel(tr("年龄:")); AgeLineEdit =new QLineEdit; OtherLabel =new QLabel(tr("备注:")); OtherLabel->setFrameStyle(QFrame::Panel|QFrame::Sunken); LeftLayout =new QGridLayout(); LeftLayout->addWidget(UserNameLabel,0,0); //用户名 LeftLayout->addWidget(UserNameLineEdit,0,1); LeftLayout->addWidget(NameLabel,1,0); //姓名 LeftLayout->addWidget(NameLineEdit,1,1); LeftLayout->addWidget(SexLabel,2,0); //性别 LeftLayout->addWidget(SexComboBox,2,1); LeftLayout->addWidget(DepartmentLabel,3,0); //部门 LeftLayout->addWidget(DepartmentTextEdit,3,1); LeftLayout->addWidget(AgeLabel,4,0); //年龄 LeftLayout->addWidget(AgeLineEdit,4,1); LeftLayout->addWidget(OtherLabel,5,0,1,2); //其他 LeftLayout->setColumnStretch(0,1); LeftLayout->setColumnStretch(1,3); /*********右侧*********/ HeadLabel =new QLabel(tr("头像:"));//右上角部分 HeadIconLabel =new QLabel; QPixmap icon("37.png");// HeadIconLabel->setPixmap(icon);// HeadIconLabel->resize(icon.width(),icon.height());// UpdateHeadBtn =new QPushButton(tr("更新")); TopRightLayout =new QHBoxLayout(); TopRightLayout->setSpacing(20); TopRightLayout->addWidget(HeadLabel); TopRightLayout->addWidget(HeadIconLabel); TopRightLayout->addWidget(UpdateHeadBtn); IntroductionLabel =new QLabel(tr("个人说明:"));//右下角部分 IntroductionTextEdit =new QTextEdit; RightLayout =new QVBoxLayout(); RightLayout->setMargin(10); RightLayout->addLayout(TopRightLayout); RightLayout->addWidget(IntroductionLabel); RightLayout->addWidget(IntroductionTextEdit); /********************** 底部 ********************* / OkBtn =new QPushButton(tr("确定")); CancelBtn =new QPushButton(tr("取消")); ButtomLayout =new QHBoxLayout(); ButtomLayout->addStretch(); ButtomLayout->addWidget(OkBtn); ButtomLayout->addWidget(CancelBtn); /************************************************/ QGridLayout *mainLayout =new QGridLayout(this); mainLayout->setMargin(15); mainLayout->setSpacing(10); mainLayout->addLayout(LeftLayout,0,0); mainLayout->addLayout(RightLayout,0,1); mainLayout->addLayout(ButtomLayout,1,0,1,2); mainLayout->setSizeConstraint(QLayout::SetFixedSize); }
其中:
● OtherLabel->setFrameStyle(QFrame::Panel|QFrame::Sunken):设置控件的风格。setFrameStyle()是QFrame的方法,参数以或(|)的方式设定控件的面板风格,由形状(QFrame::Shape)和阴影(QFrame::shadow)两项配合设定。其中,形状包括6种,分别是NoFrame、Panel、Box、HLine、VLine以及WinPanel;阴影包括3种,分别是Plain、Raised和Sunken。
● LeftLayout =new QGridLayout():左部布局,由于此布局管理器不是主布局管理器,因此不用指定父窗口。
● LeftLayout->addWidget(UserNameLabel,0,0):向布局中加入需布局的控件。
● LeftLayout->setColumnStretch(0,1)、LeftLayout->setColumnStretch(1,3):设定两列分别占用空间的比例,此处设定为1:3。即使对话框框架大小改变了,两列之间的宽度比依然保持不变。
● TopRightLayout =new QHBoxLayout():完成右上侧的头像选择区的布局。
● TopRightLayout->setSpacing(20):设定各个控件之间的间距为20。
● RightLayout =new QVBoxLayout():完成右侧的布局。
● ButtomLayout =new QHBoxLayout():完成下方两个按钮的布局。
● ButtomLayout->addStretch():在按钮之前插入一个占位符,使两个按钮能靠右对齐,并且在整个对话框的大小发生改变时,保证按钮的大小不发生变化。
● QGridLayout *mainLayout =new QGridLayout(this):实现主布局,指定父窗口this,也可调用this->setLayout(mainLayout)实现。
● mainLayout->setMargin(15):设定对话框的边距为15。
● mainLayout->setSizeConstraint(QLayout::SetFixedSize):设定最优化显示,并且用户无法改变对话框的大小。所谓最优化显示,即控件都按其sizeHint()的大小显示。
(4) 在dialog.cpp文件的开始部分加入以下头文件:
#include<QLabel> #include<QLineEdit> #include<QComboBox> #include<QPushButton> #include<QFrame> #include<QGridLayout> #include<QPixmap> #include<QHBoxLayout>
(5) 打开main.cpp文件,在主函数中添加以下加黑代码:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec::setCodecForTr(QTextCodec::codecForLocale()); //在窗口中
显示中文
Dialog w;
w.show();
return a.exec();
}
(6) 运行程序,显示效果如图4.7所示。
此实例是通过编写代码实现的,在这里还可以采用Qt Designer来进行布局。
注意:QHBoxLayout默认采取的是自左向右的方式顺序排列插入控件或子布局,也可通过调用setDirection()方法设定排列的顺序(如:layout-> setDirection(QBoxLayout::RightToLeft))。QVBoxLayout默认采取的是自上而下的方式顺序排列插入控件或子布局,也可通过调用setDirection()方法设定排列的顺序。