4.5 综合例子:修改用户资料
通过实现修改用户资料功能这一综合实例,介绍如何使用布局方法实现一个复杂的窗口布局,如何使用分割窗口以及如何使用堆栈窗体,效果如图4.9所示。见代码CH405。
图4.9 修改用户资料实例
最外层是一个分割窗体QSplitter,分割窗体的左侧是一个QListWidget,右侧是一个QVBoxLayout布局,此布局包括一个堆栈窗体QStackWidget和一个按钮布局。在此堆栈窗体QStackWidget中包含3个窗体,每个窗体采用基本布局方式进行布局管理,如图4.10所示。
图4.10 布局框架
具体实现步骤如下:
1.完成“修改用户基本信息”功能
(1) 首先建立一个工程,单击“File”→“New File or Project...”,在弹出的对话框中选择Projects组下的“Empty Qt4 Project”,单击“OK”按钮,将该工程命名(Name)为Example。选择保存该文件的路径,单击“Next”按钮,最后单击“Finish”按钮,完成该文件工程的建立。
(2) 在图4.6所示的布局框架中,框架右侧的页面可以作为独立的类来实现,即下面介绍的Content类实现。
(3) 下面添加该工程的提供主要显示界面的函数所在的文件,在“Example”项目名上单击鼠标右键,在弹出的快捷菜单中选择“Add New...”菜单项,在弹出的对话框中选择“C++ Class”选项,单击“OK”按钮,弹出“C++ Class Wizard”对话框,在Base class后面的下拉列表框中输入基类名“QFrame”(在下列列表框没有的基类,可手工添加),在Class name后面的文本框中输入类的名称“Content”,如图4.11所示。
图4.11 Enter class name
(4) 单击“Next”按钮,单击“Finish”按钮,在该工程中就添加了content.h头文件和content.cpp源文件。
(5) 打开“content.h”头文件,Content类继承自QFrame类,类声明中包含自定义的3个页面类对象、声明了两个按钮对象以及一个堆栈窗体对象,添加如下代码:
//添加的头文件 #include <QStackedWidget> #include <QPushButton> #include "baseinfo.h" #include "contact.h" #include "detail.h" class Content : public QFrame { Q_OBJECT public: Content(QWidget *parent=0); QStackedWidget *stack; QPushButton *AmendBtn; QPushButton *CloseBtn; BaseInfo *baseInfo; Contact *contact; Detail *detail; };
(6) 打开“Content.cpp”文件,添加如下代码:
Content::Content(QWidget *parent) :QFrame(parent) { stack =new QStackedWidget(this); stack->setFrameStyle(QFrame::Panel|QFrame::Raised); baseInfo =new BaseInfo(); contact =new Contact(); detail =new Detail(); stack->addWidget(baseInfo); stack->addWidget(contact); stack->addWidget(detail); AmendBtn =new QPushButton(tr("修改")); CloseBtn =new QPushButton(tr("关闭")); QHBoxLayout *BtnLayout =new QHBoxLayout; BtnLayout->addStretch(1); BtnLayout->addWidget(AmendBtn); BtnLayout->addWidget(CloseBtn); QVBoxLayout *RightLayout =new QVBoxLayout(this); RightLayout->setMargin(10); RightLayout->setSpacing(6); RightLayout->addWidget(stack); RightLayout->addLayout(BtnLayout); }
其中:
● stack =new QStackedWidget(this):创建一个QStackedWiget对象。
● stack->setFrameStyle(QFrame::Panel|QFrame::Raised):对堆栈窗的显示风格进行设置。
● baseInfo =new BaseInfo()到 stack->addWidget(detail)这段代码是在堆栈窗口中顺序插入“基本信息”、“联系方式”及“详细资料”3个页面。其中BaseInfo类的具体完成代码参照前面的4.4节,后两个与此类似。
● AmendBtn =new QPushButton(tr("修改"))到 BtnLayout->addWidget(CloseBtn)这段代码创建两个按钮,并用QHBoxLayout对其进行布局。
● QVBoxLayout *RightLayout =new QVBoxLayout(this):进行整体布局。
(7) 下面添加该工程的提供主要显示用户基本信息界面的函数所在的文件,在“Example”项目名上单击鼠标右键,在弹出的快捷菜单中选择“Add New...”菜单项,在弹出的对话框中选择“C++ Class”选项,单击“OK”按钮,弹出“C++ Class Wizard”对话框,在Base class后面的下拉列表框中输入基类名“QWidget”,在Class name后面的文本框中输入类的名称“BaseInfo”。
(8) 单击“Next”按钮,单击“Finish”按钮,添加baseinfo.h头文件和baseinfo.cpp源文件。
(9) 打开“baseinfo.h”头文件,添加的代码如下(具体解释请参照4.4节):
//添加的头文件 #include <QLabel> #include <QLineEdit> #include <QComboBox> #include <QTextEdit> #include <QGridLayout> #include <QPushButton> class BaseInfo : public QWidget { Q_OBJECT public: BaseInfo(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; };
(10) 打开“baseinfo.cpp”文件,添加如下代码(具体解释请参照4.4节):
BaseInfo::BaseInfo(QWidget *parent) :QWidget(parent) { /**** 左侧 ****/ 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("312.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); /*************************************/ QGridLayout *mainLayout =new QGridLayout(this); mainLayout->setMargin(15); mainLayout->setSpacing(10); mainLayout->addLayout(LeftLayout,0,0); mainLayout->addLayout(RightLayout,0,1); mainLayout->setSizeConstraint(QLayout::SetFixedSize); }
2.完成“显示用户的联系方式”功能
(1) 下面添加该工程的提供主要显示用户的联系方式界面的函数所在的文件,在“Example”项目名上单击鼠标右键,在弹出的快捷菜单中选择“Add New...”菜单项,在弹出的对话框中选择“C++ Class”选项。单击“OK”按钮,弹出“C++ Class Wizard”对话框,在Base class后面的下拉列表框中输入基类名“QWidget”,在Class name后面的文本框中输入类的名称“Contact”。
(2) 单击“Next”按钮,单击“Finish”按钮,添加contact.h头文件和contact.cpp源文件。
(3) 打开“contact.h”头文件,添加如下代码:
//添加的头文件 #include <QLabel> #include <QGridLayout> #include <QLineEdit> #include <QCheckBox> class Contact : public QWidget { Q_OBJECT public: Contact(QWidget *parent=0); private: QLabel *EmailLabel; QLineEdit *EmailLineEdit; QLabel *AddrLabel; QLineEdit *AddrLineEdit; QLabel *CodeLabel; QLineEdit *CodeLineEdit; QLabel *MoviTelLabel; QLineEdit *MoviTelLineEdit; QCheckBox *MoviTelCheckBook; QLabel *ProTelLabel; QLineEdit *ProTelLineEdit; QGridLayout *mainLayout; };
(4) 打开“contact.cpp”文件,添加如下代码:
Contact::Contact(QWidget *parent) :QWidget(parent) { EmailLabel =new QLabel(tr("电子邮件:")); EmailLineEdit =new QLineEdit; AddrLabel =new QLabel(tr("联系地址:")); AddrLineEdit =new QLineEdit; CodeLabel =new QLabel(tr("邮政编码:")); CodeLineEdit =new QLineEdit; MoviTelLabel =new QLabel(tr("移动电话:")); MoviTelLineEdit =new QLineEdit; MoviTelCheckBook =new QCheckBox(tr("接收留言")); ProTelLabel =new QLabel(tr("办公电话:")); ProTelLineEdit =new QLineEdit; mainLayout =new QGridLayout(this); mainLayout->setMargin(15); mainLayout->setSpacing(10); mainLayout->addWidget(EmailLabel,0,0); mainLayout->addWidget(EmailLineEdit,0,1); mainLayout->addWidget(AddrLabel,1,0); mainLayout->addWidget(AddrLineEdit,1,1); mainLayout->addWidget(CodeLabel,2,0); mainLayout->addWidget(CodeLineEdit,2,1); mainLayout->addWidget(MoviTelLabel,3,0); mainLayout->addWidget(MoviTelLineEdit,3,1); mainLayout->addWidget(MoviTelCheckBook,3,2); mainLayout->addWidget(ProTelLabel,4,0); mainLayout->addWidget(ProTelLineEdit,4,1); mainLayout->setSizeConstraint(QLayout::SetFixedSize); }
3.完成“显示用户的详细资料”功能
(1) 下面添加该工程的提供主要显示用户的详细资料界面的函数所在的文件,在“Example”项目名上单击鼠标右键,在弹出的快捷菜单中选择“Add New...”菜单项,在弹出的对话框中选择“C++ Class”选项,单击“OK”按钮,弹出“C++ Class Wizard”对话框,在Base class后面的下拉列表框中输入基类名“QWidget”,在Class name后面的文本框中输入类的名称“Detail”。
(2) 单击“Next”按钮,单击“Finish”按钮,添加detail.h头文件和detail.cpp源文件。
(3) 打开“detail.h”头文件,添加如下代码:
//添加的头文件 #include <QLabel> #include <QComboBox> #include <QLineEdit> #include <QTextEdit> #include <QGridLayout> class Detail : public QWidget { Q_OBJECT public: Detail(QWidget *parent=0); private: QLabel *NationalLabel; QComboBox *NationalComboBox; QLabel *ProvinceLabel; QComboBox *ProvinceComboBox; QLabel *CityLabel; QLineEdit *CityLineEdit; QLabel *IntroductLabel; QTextEdit *IntroductTextEdit; QGridLayout *mainLayout; };
(4)打开“detail.cpp”文件,添加如下代码:
Detail::Detail(QWidget *parent) :QWidget(parent) { NationalLabel =new QLabel(tr("国家/地址:")); NationalComboBox =new QComboBox; NationalComboBox->insertItem(0,tr("中国")); NationalComboBox->insertItem(1,tr("美国")); NationalComboBox->insertItem(2,tr("英国")); ProvinceLabel =new QLabel(tr("省份:")); ProvinceComboBox =new QComboBox; ProvinceComboBox->insertItem(0,tr("江苏省")); ProvinceComboBox->insertItem(1,tr("山东省")); ProvinceComboBox->insertItem(2,tr("浙江省")); CityLabel =new QLabel(tr("城市:")); CityLineEdit =new QLineEdit; IntroductLabel =new QLabel(tr("个人说明:")); IntroductTextEdit =new QTextEdit; mainLayout =new QGridLayout(this); mainLayout->setMargin(15); mainLayout->setSpacing(10); mainLayout->addWidget(NationalLabel,0,0); mainLayout->addWidget(NationalComboBox,0,1); mainLayout->addWidget(ProvinceLabel,1,0); mainLayout->addWidget(ProvinceComboBox,1,1); mainLayout->addWidget(CityLabel,2,0); mainLayout->addWidget(CityLineEdit,2,1); mainLayout->addWidget(IntroductLabel,3,0); mainLayout->addWidget(IntroductTextEdit,3,1); }
4.添加主函数
(1) 下面添加该工程的入口函数所在的文件(main.cpp文件),在“Example”项目名上单击鼠标右键,在弹出的快捷菜单中选择“Add New...”菜单项,在弹出的对话框中选择“C++ Source File”选项。单击“OK”按钮,弹出“New C++ Source File”对话框,在name后面的文本框中输入“main.cpp”。
(2) 单击“Next”按钮,单击“Finish”按钮,添加main函数。
(3) 打开“main.cpp”文件,添加以下代码:
#include <QApplication> #include "content.h" #include <QTextCodec> #include <QSplitter> #include <QListWidget> int main(int argc,char *argv[]) { QApplication app(argc,argv); QFont font("AR PL KaitiM GB",12); app.setFont(font); QTextCodec::setCodecForTr(QTextCodec::codecForLocale()); QSplitter *splitterMain =new QSplitter(Qt::Horizontal,0); splitterMain->setOpaqueResize(true); QListWidget *list =new QListWidget(splitterMain); list->insertItem(0,QObject::tr("基本信息")); list->insertItem(1,QObject::tr("联系方式")); list->insertItem(2,QObject::tr("详细资料")); Content *content =new Content(splitterMain); QObject::connect(list,SIGNAL(currentRowChanged(int)),content->stack, SLOT(setCurrentIndex(int))); splitterMain->setWindowTitle(QObject::tr("修改用户资料")); splitterMain->setMinimumSize(splitterMain->minimumSize()); splitterMain->setMaximumSize(splitterMain->maximumSize()); splitterMain->show(); return app.exec(); }
其中:
● QFont font("AR PL KaitiM GB",12)、app.setFont(font):设置整个程序采用的字体与字号。
● QTextCodec::setCodecForTr(QTextCodec::codecForLocale()):能够显示中文。
● QSplitter *splitterMain =new QSplitter(Qt::Horizontal,0):新建一个水平分割窗对象,作为主布局框。
● QListWidget *list =new QListWidget(splitterMain):在新建的水平分割窗的左侧中插入一个QListWidget作为条目选择框,并在此依次插入“基本信息”、“联系方式”及“详细资料”条目。
● Content *content =new Content(splitterMain):在新建的水平分割窗的右侧中插入Content类对象。
● QObject::connect(list,SIGNAL(currentRowChanged(int)),content->stack,SLOT (setCurrentIndex(int))):连接列表框的currentRowChanged()信号与堆栈窗的setCurrentIndex()槽函数。
● splitterMain->setWindowTitle(QObject::tr("修改用户资料")):设置主布局框即水平分割窗的标题。
● splitterMain->setMinimumSize(splitterMain->minimumSize()):设置主布局框即水平分割窗的最小大小。
● splitterMain->setMaximumSize(splitterMain->maximumSize()):设置主布局框即水平分割窗的最大大小。
● splitterMain->show():显示主布局框,其上面的控件一同显示。
(4) 编译运行此程序,此时未看到加载的图片,是因为图片放置的路径不是默认的,只要将所用到的图片放置到该工程下的debug文件夹下即可,最后运行一下程序,效果如图4.5所示。
要达到同样的显示效果,会有多种可能的布局方案,在实际应用中,应根据具体情况进行选择,使用最方便合理的布局方式。
注意:一般来说,QGridLayout功能能完成QHBoxLayout与QVBoxLayout的功能,但若只是完成简单的水平或竖直的排列,使用后两个更方便,QGridLayout适合较为方正整齐的界面布局。