热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Qt图形图像开发之QT滚动区控件(滚动条)QScrollArea的详细方法用法图解与实例

这篇文章主要介绍了Qt图形图像开发,QT滚动区控件(滚动条)QScrollArea的详细方法用法图解与实例,需要的朋友可以参考下

QT滚动区控件(滚动条控件)QScrollArea简介

滚动区域控件QScrollArea用于显示一个画面中的子部件的内容。如果部件超过画面的大小,视图可以提供滚动条,这样就可以看到部件的整个区域。

QScrollArea属于控件容器类,可以直接在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的标准编程步骤,分这么几种情况:

QScrollArea纯代码实现

(1) new QscrollArea

(2) new 内部的幕布容器

(3) new 布局,例如网格布局QGridLayout(前3步不分先后顺序)或者你想用的其他布局

(4) 向布局中添加你想要的控件(这一步必须位于步骤3之后,这不是废话吗)

(5) 关联"幕布控件"和"布局"(如果在创建布局时,就把布局构造在了幕布控件中,那么这一步就省了)

(6) 给QScroolArea设置幕布,也即调用QScrollArea::setWidget(QWidget *),这一步必须位于步骤4、5之后。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 
#include 
 
MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
 
  QScrollArea * scrollArea = new QScrollArea(this);
  QWidget * pWgt = new QWidget;
 
  QHBoxLayout *pLayout = new QHBoxLayout();//网格布局
    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);//把按钮添加到布局控件中
    }
  pWgt->setLayout(pLayout);
 
  //这一句setWidget必须放在pWgt里面的内容都准备完毕之后,否则显示有问题
  scrollArea->setWidget(pWgt);
  setCentralWidget(scrollArea);
}
 
MainWindow::~MainWindow()
{
  delete ui;
}

QScrollArea是直接从ui里拖出来

滚动区里面的控件是代码new的,那么编程步骤如下:

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

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

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

&#160;

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

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

最后再看几个实例

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

我们运行一下程序,然后把窗口缩小,看看是不是当窗口

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

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

再补充几点:

内部的小QWidget与QScrollArea的关系,就像是给QScrollArea设置了网格布局,然后把小QWidget放进了这个布局中,如果给小QWidget设置的最大宽高

技巧:

通过上述操作,我们知道了,我们可以通过设置内部小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中
}

本文主要讲解了QT滚动区控件(滚动条)QScrollArea的详细方法用法图解与实例,更多关于QT图形图像开发知识请查看下面的相关链接


推荐阅读
  • Docker的安全基准
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 本文详细探讨了Netty中Future及其子类的设计与实现,包括其在并发编程中的作用和具体应用场景。我们将介绍Future的继承体系、关键方法的实现细节,并讨论如何通过监听器和回调机制来处理异步任务的结果。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • Ralph的Kubernetes进阶之旅:集群架构与对象解析
    本文深入探讨了Kubernetes集群的架构和核心对象,详细介绍了Pod、Service、Volume等基本组件,以及更高层次的抽象如Deployment、StatefulSet等,帮助读者全面理解Kubernetes的工作原理。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 本文详细探讨了Java中StringBuffer类在不同情况下的扩容规则,包括空参构造、带初始字符串和指定初始容量的构造方法。通过实例代码和理论分析,帮助读者更好地理解StringBuffer的内部工作原理。 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • 深入了解 Windows 窗体中的 SplitContainer 控件
    SplitContainer 控件是 Windows 窗体中的一种复合控件,由两个可调整大小的面板和一个可移动的拆分条组成。本文将详细介绍其功能、属性以及如何通过编程方式创建复杂的用户界面。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 本文探讨了在Linux系统上使用Docker时,通过volume将主机上的HTML5文件挂载到容器内部指定目录时遇到的403错误,并提供了解决方案和详细的操作步骤。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
author-avatar
小菠萝
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有