Qt之自定义布局管理器(QCardLayout)

简述

手动布局另一种方法是通过继承QLayout类编写自己的布局管理器。

下面我们详细来举一个例子-QCardLayout。它由同名的Java布局管理器启发而来。也被称之为卡片布局,每个项目偏移QLayout::spacing()。

  • 简述
  • 定义
  • 实现
    • 效果
    • 源码

定义

编写自己的布局,必须定义如下:

  • 一种存储布局处理项目的数据结构,每个项目都是一个QLayoutItem,本例使用QList。
  • addItem() 如何添加项目布局。
  • setGeometry() 如何控制布局。
  • sizeHint() 布局的优选大小。
  • itemAt() 如何遍历布局。
  • takeAt() 如何删除布局中的项目。

大多数情况下,也会实现的minimumSize()。

实现

效果

源码

QCardLayoud.h

#ifndef QCARDLAYOUT_H
#define QCARDLAYOUT_H

#include <QWidget>
#include <QLayout>
#include <QLayoutItem>

class QCardLayout : public QLayout
{
public:
    QCardLayout(QWidget *parent = 0);
    ~QCardLayout();
    void addItem(QLayoutItem *item);
    QSize sizeHint() const;
    QSize minimumSize() const;
    int count() const;
    QLayoutItem *itemAt(int) const;
    QLayoutItem *takeAt(int);
    void setGeometry(const QRect &rect);

private:
    QList<QLayoutItem*> list;
};

#endif //QCARDLAYOUT_H

QCardLayoud.cpp

#include "QCardLayout.h"

QCardLayout::QCardLayout(QWidget *parent)
    : QLayout(parent)
{

}

// 由于QLayoutItem不继承自QObject,必须手动删除。在析构函数中,使用takeAt()删除列表中的每个项目,然后将其删除。
QCardLayout::~QCardLayout()
{
    QLayoutItem *item;
    while ((item = takeAt(0)))
        delete item;
}

// 获取列表中的项目数
int QCardLayout::count() const
{
    return list.size();
}

// 获取索引idx所对应的项目
QLayoutItem *QCardLayout::itemAt(int idx) const
{
    return list.value(idx);
}

// 移除索引idx所对应的项目,并返回
QLayoutItem *QCardLayout::takeAt(int idx)
{
    return idx >= 0 && idx < list.size() ? list.takeAt(idx) : 0;
}

// 添加项目
void QCardLayout::addItem(QLayoutItem *item)
{
    list.append(item);
}

// 实际控制着布局,作为参数提供的矩形不包括margin()。相关的,使用spacing()作为项目之间的距离。
void QCardLayout::setGeometry(const QRect &r)
{
    QLayout::setGeometry(r);

    if (list.size() == 0)
        return;

    int w = r.width() - (list.count() - 1) * spacing();
    int h = r.height() - (list.count() - 1) * spacing();
    int i = 0;
    while (i < list.size()) {
        QLayoutItem *o = list.at(i);
        QRect geom(r.x() + i * spacing(), r.y() + i * spacing(), w, h);
        o->setGeometry(geom);
        ++i;
    }
}

// sizeHint()和minimumSize()通常非常相似。这两个函数返回的尺寸应包括spacing(),但不包括margin()。
QSize QCardLayout::sizeHint() const
{
    QSize s(0,0);
    int n = list.count();
    if (n > 0)
        s = QSize(100,70);
    int i = 0;
    while (i < n) {
        QLayoutItem *o = list.at(i);
        s = s.expandedTo(o->sizeHint());
        ++i;
    }
    return s + n*QSize(spacing(), spacing());
}

QSize QCardLayout::minimumSize() const
{
    QSize s(0,0);
    int n = list.count();
    int i = 0;
    while (i < n) {
        QLayoutItem *o = list.at(i);
        s = s.expandedTo(o->minimumSize());
        ++i;
    }
    return s + n*QSize(spacing(), spacing());
}
时间: 2024-08-14 04:56:50

Qt之自定义布局管理器(QCardLayout)的相关文章

Qt之自定义布局管理器(QFlowLayout)

简述 QFlowLayout,顾名思义-流布局,实现了处理不同窗口大小的布局.根据应用窗口的宽度来进行控件放置的变化. 具体实现要求不再赘述,请参考前两节内容. 简述 实现 效果 源码 实现 QFlowLayout主要采用QLayout和QWidgetItem实现,而窗口使用了QWidget和QPushButton. 效果 源码 QFlowLayout.h #ifndef QFLOWLAYOUT_H #define QFLOWLAYOUT_H #include <QLayout> #inclu

Qt之自定义布局管理器(QBorderLayout)

简述 QBorderLayout,顾名思义-边框布局,实现了排列子控件包围中央区域的布局. 具体实现要求不再赘述,请参考前几节内容. 简述 实现 效果 源码 使用 实现 QBorderLayout主要采用QLayout和QWidgetItem实现,而窗口使用了QWidget,中央窗体使用QTextBrowser,四周以QLabel排列. 效果 源码 QBorderLayout.h #ifndef QBORDERLAYOUT_H #define QBORDERLAYOUT_H #include <

Qt学习四 - 布局管理器

开发界面程序,一定会涉及到布局的问题.我们需要让控件显示在理想中的位置,可以直接设置控件的坐标和宽高.但是这样带来一个问题,当用户改变窗口大小时,例如点击最大化按钮或者拖拽窗口边缘,控件是不会改变的(包括控件的坐标和宽高).因为在窗口改变时,你没有告诉程序是否更新控件以及如何更新.如果需要让控件自动更新,那么就要自己来写一些函数来相应这些变化.针对这种情况,Qt提供了一种机制 - 布局,来解决这个问题(大部分用于开发界面程序的语言或者框架,都会提供类似的机制).只需要将控件放入某一种布局,当位置

Qt垂直/水平布局管理器(QBoxLayout,QHBoxLayout, QVBoxLayout)

1.解释 QBoxLayout:可以在水平方向或垂直方向上排列控件,由QHBoxLayout.QVBoxLayout所继承. QHBoxLayout:水平布局,在水平方向上排列控件. QVBoxLayout:垂直布局,在垂直方向上排列控件. 同时我们注意到水平布局.垂直布局除了构造时的方向(LeftToRight.TopToBottom)不同外,其它均相同. 2.示例代码 2.1QHBoxLayout, QVBoxLayout实现 1 #include "widget.h" 2 #in

Qt布局管理器(详解)

1.存在的问题 (1)目前的GUI开发方式:绝对定位 --直接在像素级指定各个组件的位置和大小 void QWidget::move(int x, int y) void QWidget::resize(int w, int h) (2)问题 --组件位置和大小无法自适应父窗口的变化 2.布局管理器 (1)解决方案:布局管理器 --提供相关的类对界面组件进行布局管理 @1:能够自动排列窗口中的界面组件 @2:窗口变化后自动更新界面组件的大小 (2)QLayout是Qt中布局管理器的抽象基类 (3

QT之布局管理器(十九)

我们在之前的 GUI 开发中都是使用的是绝对定位,何谓绝对定位呢?就是我们直接在像素级指定各个组件的位置和大小.比如我们之前使用的 void QWidget::move(int x, int y):void QWidget::resize(int w, int h):这样存在的问题就是组件的位置和大小无法自适应父窗口的变化. 我们先来看看绝对定位的代码和效果是怎样的?头文件代码如下: #include <QWidget> #include <QPushButton> class W

Qt 布局管理器

在一个颜值当道的今天,无论买衣服,买车还是追星,颜值的高低已经变成了大家最看重的(不管男性女性都一样,千万别和我说你不是):而对于程序猿来说,开发一款软件,不再只注重逻辑和稳定性,美观和用户友好性也是我们不得不关注的一个重点了. 我们进入正题,今天主要和大家分享一下Qt方面关于布局管理器的使用: 一.基本概念   Qt 提供了几种在窗口部件上管理子窗口部件的基本方式.一共有3 种方法用于管理窗体上子窗口部件的布局:绝对位置法.人工布局法和布局管理器法.相比于使用固定尺寸和位置,布局提供了功能强大

第22课 布局管理器(一)

1. 绝对定位及存在的问题 (1)直接在像素级指定各个组件的位置和大小 void QWidget::move(int x, int y) void QWidget::resize(int w, int h); (2)存在问题:组件的位置和大小无法自适应父窗口的变化 2. 布局管理器 (1)提供相关的类对界面组件进行布局管理 ①能够自动排列窗口中的界面组件 ②窗口变化后自动更新界面组件的大小 (2)QLayout是Qt中布局管理器的抽象基类 (3)通过继承QLayout实现了功能各异且互补的布局管

【Java Swing探索之路系列】之三:Java Swing布局管理器组件

作者:郭嘉 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell 一 BorderLayout BorderLayout是一种简单的布局策略,可以将其看作一个组件.它把容器分为东.南.西.北.中5个区域,每个组件将占据某个区域.而 这5个区域分别被命名为NORTH, WEST, EAST, CENTER, SOUTH,它们都被定义为静态 常量.静态常量可以直接引用,如