[转]QT的自动滚动区QScrollArea的用法,图文详解

14 篇文章 0 订阅
3 篇文章 0 订阅

本文转载于:QT的自动滚动区QScrollArea的用法,图文详解

ScrollArea属于控件容器类,可以直接在ui中拖出来。

对于QScrollArea,最难搞懂的就是:如何控制它,才能让它在我们想要出现滚动条的时候出现滚动条。

我们拖入一个QScrollArea,再向他里面拖入4个button,观察信息如下:

可以发现,4个button并不是直接位于QScrollArea中的,而是位于它的成员scorllAreaWidgetContents中的,这个成员的类型也是控件类型QWidget,也就是说,QScrollArea这个容器本身就套了两层,我们放入的按钮等控件,都处在scrllAreaWidgetContents层,下文中我把QScrollArea.widget统一称之为“内部容器”或者"内容层",内部容器是QScrollArea这个控件的子控件。

"内容层"相当于一块很大的幕布,按钮、label等控件都被绘制在了幕布上,而QScrollArea相当于一个小窗口,透过这个小窗口我们看一看到幕布上的一小部分内容,拖动滚动条相当于在窗口后面移动幕布,这样我们就能透过窗口看到幕布上不同位置的内容。

这个幕布本质上就是一个QWidget,如果QScrollArea是从UI设计师界面拖出来的,那么QT会自动为我们创建这个幕布,如果你是用代码new出来的QScrollArea,那么不要忘记同时new一个幕布widget,并通过QScrollArea::setWidget(QWidget *)把幕布和QScrollArea关联起来。

这里有一个坑,如果你写了一个功能更强的QScrollArea的子类,假设叫QScrollAreaEx(里面自带幕布,幕布中自带一些按钮什么的),在ui设计师界面把QScrollArea提升为QScrollAreaEx的时候,你会发现,按钮并没有显示出来,why?因为QT自动生成的ui代码中,new了一个幕布控件,并把这个空的幕布赋给了QScrollAreaEx对象,这真是太坑了。解决方案有两种,①自己用代码new QScrollAreaEx,②在ui中拖出一个非QScrollArea的QWidget控件,然后提升为QScrollAreaEx。

 

 

一旦理解了幕布和观察窗口的关系,就能很容易的总结出QScrollArea的标准编程步骤,分这么几种情况:

    情形1,纯代码实现

(1)new QscrollArea
(2)new 内部的幕布容器
(3)new 布局,例如网格布局QGridLayout(前3步不分先后顺序)或者你想用的其他布局
(4)向布局中添加你想要的控件(这一步必须位于步骤3之后,这不是废话吗)
(5)关联"幕布控件"和"布局"(如果在创建布局时,就把布局构造在了幕布控件中,那么这一步就省了)
(6)给QScroolArea设置幕布,也即调用QScrollArea::setWidget(QWidget *),这一步必须位于步骤4、5之后。

    情形2,QScrollArea是直接在ui里拖出来的,滚动区里面的控件是代码new的,那么编程步骤如下:

只做上一种情形的步骤(3)(4)(5)即可。

    情形3,QScrollArea和它里面的控件都是直接在ui里拖出来的

这种情形不用写代码,只要在滚动区域把控件摆放好,然后使用任意一种布局即可,如下2图所示:

 

   一句话总结何时出现滚动条:

只要幕布控件scorllAreaWidgetContents的大小超过了QScrollArea的大小,就会自动出现滚动条;如果幕布比观察窗口还小,那就不会出现滚动条。

最后再看几个实例,

我给scorllAreaWidgetContents成员设置宽高最小值为500*1000,这么高的scorllAreaWidgetContents,显然QScrollArea在高度上是无法容纳下的。实际上,看效果发现,还没有运行程序,就已经有滚动条了:

 

我们运行一下程序,然后把窗口缩小,看看是不是当窗口<scorllAreaWidgetContents最小值500*1000时,会自动出现水平滚动条。看下图发现,并没有出现我们期望的效果。

原因就是,水平滚动条,只有当QScrollArea<内部的QWidget时,才会出现,显然上图中,QScrollArea虽然没显示全,但是QScrollArea的宽度仍然保持原值,只是被遮住了而已。要想使QScrollArea的宽度变小,要么通过程序直接修改,要么通过设置布局,使QScrollArea的宽度随窗体的宽度减小而减小。我们这里就简单一点,直接给窗体设置网格布局:

使得QScrollArea的大小受窗体大小驱动。运行起来,再看下效果:

再补充几点:

内部的小QWidget与QScrollArea的关系,就像是给QScrollArea设置了网格布局,然后把小QWidget放进了这个布局中,如果给小QWidget设置的最大宽高<QScrollArea的实时大小,那么QScrollArea会显示出空白,而空白部分是无法放置/显示我们自己拖入的控件的,如下图:

技巧:

通过上述操作,我们知道了,我们可以通过设置内部小QWidget的宽、高最小值,来让外部QScrollArea适时的出现滚动条,那么到底把小QWidget的宽、高最小值设置为多少合适呢?

答案是显然的:把小QWidget的宽、高最小值设置为刚好能容纳内部的按钮等控件,这样看起来最舒服。难道我要先计算或者观察一下按钮等控件占用的面积之后,才能去设置小QWidget的宽、高最小值吗?

这样做太费劲了,我们肯定不会去这样做,除非是用ui设计师拖控件时,所见即所得,才无需计算小QWidget的宽、高最小值。用代码写界面时,最好的做法是:

1、向小QWidget中添加按钮等控件时,随着添加的按钮增多,小QWidget自动变大,显然用QGridLayout来做就能实现这个自动增大这个需求。自动增大也只是出现创建内部容器阶段,一旦内部容器和布局、布局内的控件都创建和添加完毕,后续即使再向布局中添加控件,内部容器也不会自动增大了,这时只有靠setGeometry或者resize手动修改内部容器的大小了。

2、添加完控件后,手动调用一下adjustSize函数,该函数会根据所有子控件的大小之和,来调整父控件的大小。

步骤如下:先在ui中拖入一个QScrollArea控件,名字为scrollArea,然后添加代码:

   

MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
     
        QGridLayout *pLayout = new QGridLayout();//网格布局
        for(int i = 0; i < 100; i++)
        {
            QPushButton *pBtn = new QPushButton();
            pBtn->setText(QString("按钮%1").arg(i));
            pBtn->setMinimumSize(QSize(60,30));   //width height
            pLayout->addWidget(pBtn);//把按钮添加到布局控件中
        }
        ui->scrollArea->widget()->setLayout(pLayout);//把布局放置到QScrollArea的内部QWidget中
    }


————————————————
版权声明:本文为CSDN博主「qq_610642」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_31073871/article/details/83117430

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值