今天主要学习Qt布局管理的使用方法,分别学习分割窗口(QSplitter)、停靠窗口(QDockWidget)、堆栈窗体(QStackedWidget)和基本布局的使用;
分割窗口
可以灵活分布窗口的布局,常用于类似文件资源管理器的窗口设计中,实例代码:
新建一个QWidget Application
项目,基类选择QMainWIndow
,取消ui界面,在main.cpp
进行编写代码;
#include "splitter.h"
#include <QApplication>
#include <QSplitter>
#include <QTextEdit>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 设置字体
QFont font("ZYSong18030", 12);
a.setFont(font);
// 主分割窗口, Qt::Horizontal 水平分割方式
QSplitter *mainSplitter = new QSplitter(Qt::Horizontal, 0);
// 设置窗体名字
mainSplitter->setWindowTitle(QObject::tr("main splitter"));
// 左面的输入框
QTextEdit *leftText = new QTextEdit(QObject::tr("left text"), mainSplitter);
leftText->setAlignment(Qt::AlignCenter); // 设置字体居中
// 右分割窗口,Qt::Vertical 垂直分割方式
QSplitter *rightSplitter = new QSplitter(Qt::Vertical, mainSplitter);
// setOpaqueResize() 移动窗口是否实时更新,默认为true(实时更新)
rightSplitter->setOpaqueResize(false);
// 右侧上方输入框
QTextEdit *upText = new QTextEdit(QObject::tr("up text"), rightSplitter);
upText->setAlignment(Qt::AlignCenter);
// 右侧下方输入框
QTextEdit *underText = new QTextEdit(QObject::tr("under text"), rightSplitter);
underText->setAlignment(Qt::AlignCenter);
// 设置可伸缩性,第一个参数为控件序号,第二个参数判断是否伸缩
mainSplitter->setStretchFactor(1, 1);
mainSplitter->show();
//Splitter w;
//w.show();
return a.exec();
}
实例效果如图:
停靠窗口
设置停靠窗口的一般流程如下:
(1)创建一个QDockWidget
停靠窗体对象;
(2)设置此停靠窗体的属性,常用的有setFeatures()
以及setAllowedAreas()
;
(3)新建要插入此停靠窗体的控件对象,常用的有QListWidget
和QTextEdit
;
(4)将控件对象插入到QDockWidget
中, 使用setWidget()
方法;
(5)使用addDockWidget()
方法在MainWindow
中加入停靠窗口。
停靠窗口实例:DockWindow1
只能MainWindow
在左右两边停靠,DockWindow2
只能停靠在右边或浮动,DockWindow3
可以实现停靠窗口的各种状态。
新建项目,基类选择QMainWindow
,取消ui选项,创建停靠窗口只需将代码写在构造函数当中即可:
#include "mainwindow.h"
#include <QTextEdit>
#include <QDockWidget>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(tr("DockWidget"));
this->resize(600, 600);
// 设置一个编辑框作为主窗口
QTextEdit *mainText = new QTextEdit(this);
mainText->setText(tr("Main Text"));
mainText->setAlignment(Qt::AlignCenter);
// 将此编辑框放在主窗口中央
setCentralWidget(mainText);
// DockWindow1属性设置
QDockWidget *dock = new QDockWidget(tr("DockWindow1"), this);
dock->setFeatures(QDockWidget::DockWidgetMovable); // 可移动
dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); // 可停靠左右
// DockWindow1中编辑框控件
QTextEdit *text1 = new QTextEdit();
text1->setText(tr("DockWindow1, the DockWindow can be moved between docks by the user"));
dock->setWidget(text1);
addDockWidget(Qt::RightDockWidgetArea, dock); // 右侧放入停靠窗口
// DockWindow2属性设置
QDockWidget *dock2 = new QDockWidget(tr("DockWindow2"), this);
dock2->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable); // 可关闭|可浮动
QTextEdit *text2 = new QTextEdit();
text2->setText(tr("DockWindow2, the DockWindow can be detachde from main window and float, and can be close"));
dock2->setWidget(text2);
addDockWidget(Qt::RightDockWidgetArea, dock2);
// DockWindow3属性设置
QDockWidget *dock3 = new QDockWidget(tr("DockWindow3"), this);
dock3->setFeatures(QDockWidget::AllDockWidgetFeatures); // 全部属性
QTextEdit *text3 = new QTextEdit();
text3->setText(tr("DockWindws, the DockWindow have all features"));
dock3->setWidget(text3);
addDockWidget(Qt::RightDockWidgetArea, dock3);
}
MainWindow::~MainWindow()
{
}
实例效果如下:
堆栈窗体
堆栈窗体常与列表框QListWidget
和下拉列表框QComboBox
一起使用。当选则左侧列表栏不同的选项是,显示不同的窗体。实例代码如下:
新建GUI项目,基类选择QDialog
,取消ui界面选项
头文件stackWidget.h
:
#include <QDialog>
#include <QStackedWidget>
#include <QLabel>
#include <QListWidget>
#include <QHBoxLayout>
class StackWidget : public QDialog
{
Q_OBJECT
public:
StackWidget(QWidget *parent = 0);
~StackWidget();
private:
QStackedWidget *stack;
QListWidget *list;
QLabel *label1;
QLabel *label2;
QLabel *label3;
};
界面内容设置在构造函数中完成:
StackWidget.cpp:
StackWidget::StackWidget(QWidget *parent)
: QDialog(parent)
{
this->resize(600, 600);
setWindowTitle(tr("StackWidget"));
// 创建窗口左侧的list列表,设置不同选项
list = new QListWidget(this);
list->insertItem(0, tr("window1"));
list->insertItem(1, tr("window2"));
list->insertItem(2, tr("window3"));
// 窗体右侧显示的标签内容
label1 = new QLabel(tr("first StackWidget"));
label2 = new QLabel(tr("second StackWidget"));
label3 = new QLabel(tr("third StackWidget"));
// 创建堆栈窗体,放入标签内容
stack = new QStackedWidget(this);
stack->addWidget(label1);
stack->addWidget(label2);
stack->addWidget(label3);
// 对窗体进行布局,放入list列表和标签内容
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->setMargin(5); // 设定窗体间边距
mainLayout->setSpacing(5); // 设定各个控件间边距
mainLayout->addWidget(list);
mainLayout->addWidget(stack, 0, Qt::AlignHCenter);
// 设置控件可伸缩性
mainLayout->setStretchFactor(list, 1);
mainLayout->setStretchFactor(stack, 3);
// 连接信号和槽,点击列表选项切换右侧界面显示
connect(list, &QListWidget::currentRowChanged, stack, &QStackedWidget::setCurrentIndex);
}
实例效果如图:
基本布局
Qt提供了QHBoxLayout
(水平布局)、QVBoxLayout
(垂直布局)、QGridLayout
(网格布局)等的基本布局管理;常用的方法有:addWidget()
布局中加入控件和addLayout()
布局中加入布局。
接下来使用三种布局方式实现一个简单的界面,图示如下:
对界面进行简单的分析和设计:
创建新项目,基类选择QDialog
,取消ui界面,代码实现如下:
UserInfo.h:
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include <QComboBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QPixmap>
class UserInfo : public QDialog
{
Q_OBJECT
public:
UserInfo(QWidget *parent = 0);
~UserInfo();
private:
QGridLayout *mainLayout;
// 左侧上部布局所有控件
QGridLayout *leftLayout;
QLabel *userLabel;
QLineEdit *userEdit;
QLabel *nameLabel;
QLineEdit *nameEdit;
QLabel *sexLabel;
QComboBox *sexComboBox;
QLabel *departLabel;
QTextEdit *departEdit;
QLabel *ageLabel;
QLineEdit *ageEdit;
QLabel *otherLabel;
// 右侧上部布局所有控件
QHBoxLayout *topRightLayout;
QLabel *headLabel;
QLabel *headIconLabel;
QPushButton *updateButton;
// 右侧下部布局
QLabel *introductionLabel;
QTextEdit *introductionEdit;
QVBoxLayout *rightLayout;
// 下部两个按钮的布局
QPushButton *okButton;
QPushButton *cancelButton;
QHBoxLayout *buttonLayout;
};
UserInfo.cpp的构造函数中完成界面显示
#include "userinfo.h"
UserInfo::UserInfo(QWidget *parent)
: QDialog(parent)
{
this->resize(999, 666);
setWindowTitle(tr("UserInfo"));
// 左侧控件
userLabel = new QLabel(tr("user :"));
userEdit = new QLineEdit;
nameLabel = new QLabel(tr("name :"));
nameEdit = new QLineEdit;
sexLabel = new QLabel(tr("sex :"));
// 下拉列表框
sexComboBox = new QComboBox;
sexComboBox->addItem(tr("man"));
sexComboBox->addItem(tr("woman"));
departLabel = new QLabel(tr("department :"));
departEdit = new QTextEdit;
ageLabel = new QLabel(tr("age :"));
ageEdit = new QLineEdit;
// setFrameStyle()设置控件风格
otherLabel = new QLabel(tr("other :"));
otherLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
leftLayout = new QGridLayout();
leftLayout->addWidget(userLabel, 0, 0);
leftLayout->addWidget(userEdit, 0, 1);
leftLayout->addWidget(nameLabel, 1, 0);
leftLayout->addWidget(nameEdit, 1, 1);
leftLayout->addWidget(sexLabel, 2, 0);
leftLayout->addWidget(sexComboBox, 2, 1);
leftLayout->addWidget(departLabel, 3, 0);
leftLayout->addWidget(departEdit, 3, 1);
leftLayout->addWidget(ageLabel, 4, 0);
leftLayout->addWidget(ageEdit, 4, 1);
leftLayout->addWidget(otherLabel, 5, 0, 1, 2);
// 设置占用比例
leftLayout->setColumnStretch(0, 1);
leftLayout->setColumnStretch(1, 3);
// 右侧上部
headLabel = new QLabel(tr("head :"));
// QLabel显示图片,将图片放到构建后生成的Debug目录下
headIconLabel = new QLabel;
QPixmap icon("head.jpg");
headIconLabel->setPixmap(icon);
// 调整显示图片的大小为图片本身大小
headIconLabel->resize(icon.width(), icon.height());
updateButton = new QPushButton(tr("update"));
// 右侧上部布局
topRightLayout = new QHBoxLayout();
topRightLayout->setSpacing(20);
topRightLayout->addWidget(headLabel);
topRightLayout->addWidget(headIconLabel);
topRightLayout->addWidget(updateButton);
introductionLabel = new QLabel(tr("introduction :"));
introductionEdit = new QTextEdit;
// 整个右侧的布局
rightLayout = new QVBoxLayout();
rightLayout->setMargin(10);
rightLayout->addLayout(topRightLayout);
rightLayout->addWidget(introductionLabel);
rightLayout->addWidget(introductionEdit);
// 底部按钮布局
okButton = new QPushButton(tr("OK"));
cancelButton = new QPushButton(tr("CANCEL"));
buttonLayout = new QHBoxLayout();
// 在按钮之前插入占位符,使得两个按钮可以靠右对其
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
mainLayout = new QGridLayout(this);
mainLayout->setMargin(15);
mainLayout->setSpacing(10);
mainLayout->addLayout(leftLayout, 0, 0);
mainLayout->addLayout(rightLayout, 0, 1);
mainLayout->addLayout(buttonLayout, 1, 0, 1, 2);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
}
实例效果为: