【Qt】浅谈QLayout

   作为一个半路出家的程序员,对于编程这一块的学习并不系统,通常都是需要用什么,才火急火燎的学习什么。因此很容易走一些不必要的弯路,在学习Qt开发的过程中也例外,到目前为止,接触Qt开发已经有两年多了,在踩过不少坑之后,才发现布局的重要性。在Qt开发过程中,有代码生成UI和Qt Designer设计UI这两种途径,故在界面布局的时候,既可以使用代码进行布局控制,也可以通过Designer进行具体布局。在此,就先谈谈在Qt Designer中进行界面布局。

Alt

图1 Qt Designer中关于QLayout的截图

   在Qt Designer中与QLayout相关的部分有两个,如图1所示。可在左侧窗口部件盒中选取需要的布局方式(1),也可在工具栏中选择对应的布局布局方式(2),这两部分都能达到想要的布局效果。可以根据个人习惯进行选择使用,我个人更倾向于使用工具栏中的布局方式进行布局。不过这两个部分存在几个比较有意思的事情。其中Spacers中的两个类似于弹簧的控件继承自QLayoutItem,属于布局控件,能够使得布局更加紧凑。此外就是绿色框框选的两个QSplitter,使用之后能够起到分割界面的作用,有布局器的效果,但却继承自QFrame。有兴趣的朋友也可以在Qt助手中具体研究一下。

Alt

图2 布局效果示意图

   Designer中的“Vertical Layout”和“Horzontal Layout”通常可用于纵向或者横向尺寸相似的控件布局,其效果如图2中1,2所示。“Grid Layout”通常用于类似于键盘这种同类型,多行多列控件的布局,其效果如图2中3所示的内容。“From Layout”则常用于左侧带有标签,右侧带有数据修改控件的情况,如图2中4所示。以上只是对于不同布局的举例而已,Qt的界面布局相对灵活,通常需要根据自己的实际需要选择合适的布局,从而达到美观简洁的效果。

Alt

图3 QSpliter布局效果示意图

   另外,在很多时候,由于界面需要显示很多的控件,但是又不想显示在不同的页面上,就可以使用QSpliter进行界面布局,将不需要的使用的部分或者使用频率低的部分隐藏起来,从而达到扩大主要的显示或者调整区域。如图3所示。
   在Designer中添加好需要的控件后,进行界面布局相对简单。只需要选中已经添加好的控件,选择相应的布局方式进行界面布局即可。若要通过代码控制界面布局,则难度相对会有不少提升,需要了解不同布局内容和使用方式。包括常见的QHBoxLayout、QVBoxLayout、QFromLayout和QGridLayout,以及Designer中没有显示出来的QStackedLayout。它们之间的继承关系如图4所示。需要注意的是QLayout继承自QObject和QLayoutItem,QSpacerItem和QWidgetItem继承自QLayoutItem,在图中用不同的颜色线标记出来了。
Alt

图4 与布局相关的继承关系

   首先说说最为常用的QHBoxLayout和QBoxLayout,它们的布局效果就是Designer中“Vertical Layout”和“Horzontal Layout”布局呈现的效果,用Designer设计的UI在经过编译生成的h文件中,对应的就是这两种布局方式。它们都继承自QBoxLayout。其具体使用方式,可在“Qt助手”中的索引或者搜索中进行搜索查找。以“Horzontal Layout”布局为例,其常见的创建和使用方式如下

// 方式1——直接用QHBoxLayout创建布局并添加布局内容
QHBoxLayout *hboxlayout = new QHBoxLayout();
QStringList text = {"One", "Two", "Three"};
for (int i = 0; i < text.count(); i++)
{
    QPushButton *btn = new QPushButton(text.at(i));
    hboxlayout->addWidget(btn);
}

// 方式2——使用QBoxLayout布局,通过QBoxLayout::Direction控制生成方式并添加布局内容
QBoxLayout *hboxlayout = new QBoxLayout(QBoxLayout::LeftToRight);
QStringList text = {"One", "Two", "Three"};
for (int i = 0; i < text.count(); i++)
{
    QPushButton *btn = new QPushButton(text.at(i));
    hboxlayout->addWidget(btn);
}

   QGridLayout也是很常用的布局方式之一,它具体用法相较于QBoxLayout会复杂许多。比如图2中3位置所展示的数字小键盘的实现方式如下。这只是QGridLayout最简单的一种使用方式,在实际应用中,可根据自己所遇到的情况,通过Qt助手查看关于QGridLayout的其他方法。

QGridLayout *gridlayout = new QGridLayout();
QStringList text = {"7", "8", "9", "4", "5", "6", "1", "2", "3"};
int idx = 0;
for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 3; j++)
    {
        idx = i * 3 + j;
        QPushButton *btn = new QPushButton(text.at(idx));
        gridlayout->addWidget(btn, i, j);
    }
}

   QFromLayout也是比较常用的布局方式,它是以表单的形式管理界面,包含输入控件和相应标签。其效果如图2中4位置所示。Qt帮助界面中给的样例如下

 QFormLayout *formLayout = new QFormLayout;
 formLayout->addRow(tr("&Name:"), nameLineEdit);
 formLayout->addRow(tr("&Email:"), emailLineEdit);
 formLayout->addRow(tr("&Age:"), ageSpinBox);
 setLayout(formLayout);

   QStackedLayout在一般项目中使用较少,目前见过类似且比较典型的就是海思的PQTool中的树形结构和不同模块的界面显示。只是举个例子,毕竟我也不清楚海思PQTool具体使用的开发语言。在这里,我们可以简单模拟以下,其效果如图5所示。
Alt

图5 QStackedLayout使用示意图

   图5中所展示的效果,是通过在QListWidget中切换不同的item调用不同的QLabel标签进行显示,实现代码也相对简单,可以写一个createQStackedLayout()的函数达到上述效果,其内容如下

void MainWindow::createQStackedLayout()
{
    // 创建QListWidget组件
    QListWidget *listwidget = new QListWidget();
    listwidget->addItem("item1");
    listwidget->addItem("item2");
    listwidget->addItem("item3");
	
    // 创建QLabel标签,并使内容水平和竖直均居中显示
    QLabel *label1 = new QLabel("item-1");
    label1->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    QLabel *label2 = new QLabel("item-2");
    label2->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    QLabel *label3 = new QLabel("item-3");
    label3->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
	
    // 创建QStackedLayout方式,并添加标签
    QStackedLayout *stackedlayout = new QStackedLayout();
    stackedlayout->addWidget(label1);
    stackedlayout->addWidget(label2);
    stackedlayout->addWidget(label3);
	
    // 创建一个水平布局方式,将QListWidget和stackedlayout放置其中,并以1:4的比例显示
    QHBoxLayout *hboxlayout = new QHBoxLayout();
    hboxlayout->addWidget(listwidget);
    hboxlayout->addLayout(stackedlayout);
    hboxlayout->setStretch(0, 1);
    hboxlayout->setStretch(1, 4);
	
    // 将布局添加到主界面中,便于显示
    ui->centralwidget->setLayout(hboxlayout);
	
    // 连接信号和槽函数
    QObject::connect(listwidget, &QListWidget::currentRowChanged,
                     stackedlayout,  &QStackedLayout::setCurrentIndex);
}

   在实际工程应用中,界面布局往往比上述例子要复杂的多,所以深入了解图4所示的内容很有必要。千里之行始于足下,希望自己在往后的学习过程中,更加注重基础知识的学习和掌握。

个人声明:
   以上内容,纯属个人观点,不喜勿喷。未经本人同意,不得私自转载。博客中出现的代码仅供学习参考,不得有其他用途。若文中存在纰漏,或读者有更好的建议,欢迎留言探讨。也可邮箱联系:yxyx_0212@163.com

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值