自定义缓冲池,循环利用(仿tableview)

#define kSpace 20

@interface JRScrollView(){

    CGFloat kViewWidth;

    CGFloat kViewHeight;

}

/** 保存所有frame*/

@property(nonatomic,strong) NSMutableArray * frameArray;

/** 保存所有在屏幕内的视图frame*/

@property(nonatomic,strong) NSMutableDictionary * inDic;

/** 保存缓冲池*/

@property(nonatomic,strong) NSMutableDictionary * poolDic;

@end



@implementation JRScrollView


-(NSMutableArray *)frameArray{

    if (_frameArray==nil) {

        _frameArray=[NSMutableArray array];

    }

    return _frameArray;

}

-(NSMutableDictionary *)inDic{

    if (_inDic==nil) {

        _inDic=[NSMutableDictionary dictionary];

    }

    return _inDic;

}

-(NSMutableDictionary *)poolDic{

    if (_poolDic==nil) {

        _poolDic=[NSMutableDictionary dictionary];

    }

    return _poolDic;    

}


//.....

- (instancetype)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

    }

    return self;

}


#pragma mark - 加载子视图

- (void) _addSubviews{

    

    //获取当前cell的尺寸

    kViewHeight=[self.jrDelegate sizeOfCellInScroll:self].height;

    kViewWidth=[self.jrDelegate sizeOfCellInScroll:self].width;

    

    //获取当前总的cell数目

    NSInteger totalCells=[self.jrDatasource numberOfCells:self];

    //获取当前列数

    NSInteger colums=[self.jrDatasource numberofColums:self];


    CGFloat leftSpace, rightSpace, topSpace, rowSpace;

    leftSpace=rightSpace=topSpace=rowSpace = kSpace;

    if ([self.jrDelegate respondsToSelector:@selector(jrsCroll:spaceForCellWithFlag:)]) {

        //获取左间距

        leftSpace=[self.jrDelegate jrsCroll:self spaceForCellWithFlag:JRScrollViewSpaceLeft];

        //获取右间距

        rightSpace=[self.jrDelegate jrsCroll:self spaceForCellWithFlag:JRScrollViewSpaceRight];

        //获取顶部间距

        topSpace=[self.jrDelegate jrsCroll:self spaceForCellWithFlag:JRScrollViewSpaceTop];

        //获取行间距

        rowSpace=[self.jrDelegate jrsCroll:self spaceForCellWithFlag:JRScrollViewSpaceRowSpace];

    }


    //计算所有的frame,用来判断是否在显示的视野内

    

    //水平间距

    CGFloat hspace=(self.frame.size.width-leftSpace-rightSpace-colums*kViewWidth)/(colums-1)+kViewWidth;

    if ([self.jrDelegate respondsToSelector:@selector(hspaceForJrsCroll:)]) {

        hspace = [self.jrDelegate hspaceForJrsCroll:self] + kViewWidth;

    }

    

    //竖直间距

    CGFloat vspace=kViewHeight+rowSpace;    

    for(int i=0;i<totalCells;i++){

        //获取列索引

        int col=i%colums;

        //获取行索引

        int rows=i/colums;

        

        CGRect frame=CGRectMake(leftSpace+col*hspace, topSpace+rows*vspace, kViewWidth, kViewHeight);

        [self.frameArray addObject:[NSValue valueWithCGRect:frame]];

    

    }

    NSValue *frameValue=[self.frameArray lastObject] ;

    CGRect frame=[frameValue CGRectValue];

    

    NSValue *frameValue2=self.frameArray[colums-1] ;

    CGRect frame2=[frameValue2 CGRectValue];

    CGFloat screenWidth = CGRectGetMaxX(frame2)+rightSpace;

    

    self.contentSize=CGSizeMake(screenWidth, CGRectGetMaxY(frame));

    self.showsVerticalScrollIndicator=NO;


}


-(void)layoutSubviews{

    [super layoutSubviews];   

    for (int i=0;i<self.frameArray.count;i++) {

        NSValue * value=self.frameArray[i];

        CGRect frame=[value CGRectValue];

        BOOL isInScreen=[self _isInscreen:frame];

        if (isInScreen) {

            if (!self.inDic[@(i)]) {

                UIView * view=[self.jrDatasource jrsCroll:self cellAtIndex:i];

                view.frame=frame;

                [self addSubview:view];

                [self.inDic setObject:view forKey:@(i)];

            }           

        }else{

             JRCellView * jrcell=self.inDic[@(i)];

            if (jrcell){

                //加入缓存池

                NSMutableSet * set=self.poolDic[jrcell.identy];

                [set addObject:jrcell];

                [jrcell removeFromSuperview];

                [self.inDic removeObjectForKey:@(i)];

            }

        

        }

    }

    

}


#pragma mark - 判断是不是在屏幕


- (BOOL) _isInscreen:(CGRect) frame{

     CGFloat contentY=self.contentOffset.y;

     CGFloat contentX=self.contentOffset.x;

    BOOL condition1= CGRectGetMaxY(frame)>contentY && frame.origin.y<contentY+self.frame.size.height;

    BOOL condition2= CGRectGetMaxX(frame)>contentX && frame.origin.x<contentX+self.frame.size.width;

    

    return condition1 && condition2;

}


#pragma mark - 重复利用

//获取可重复利用cell

- (JRCellView *)dequeueReusedCellWithIdenty:(NSString *) identy{

   //初始化池子

    NSMutableSet * set=self.poolDic[identy];

    if(set==nil){

        set=[NSMutableSet set];

        [self.poolDic setObject:set forKey:identy];

    }

    //如果cell被引用了,需要从池子里面删除

    JRCellView * view=[set anyObject];

    if (view!=nil) {

        [set removeObject:view];

    }

    return view ;


}

//*******

- (void) loadDatas{

    [self _addSubviews];

}

@end


要在Qt中使用TableView显示自定义数据结构,你需要将该结构转换为Qt的模型(Model)。Qt的模型-视图(Model-View)框架提供了两种模型:标准模型和自定义模型。标准模型适用于表格和列表等简单的数据结构,而自定义模型则更加灵活,适用于显示自定义数据结构。 以下是一些步骤,可以帮助你在Qt中使用TableView显示自定义数据结构: 1. 创建自定义数据结构 首先,你需要创建一个自定义数据结构,例如一个包含姓名、年龄和性别的结构体。 ```c++ struct Person { QString name; int age; QString gender; }; ``` 2. 创建自定义模型 接下来,你需要创建一个自定义模型,该模型将用于将自定义数据结构转换为Qt模型。你可以创建一个继承自QAbstractTableModel的类,并重写以下方法: ```c++ class PersonModel : public QAbstractTableModel { public: PersonModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; QList<Person> persons; private: int _rowCount; int _columnCount; }; ``` 在上面的代码中,我们创建了一个名为PersonModel的自定义模型,并重写了rowCount、columnCount、data和headerData方法。 其中,rowCount和columnCount方法返回行数和列数,data方法返回单元格的数据,headerData方法返回表头的数据。 3. 实现自定义模型的方法 接下来,你需要实现自定义模型的方法。在这里,你需要将自定义数据结构转换为Qt模型的数据。在PersonModel类中,我们使用了一个QList来存储Person结构体的数据,因此我们需要在重写的方法中将该数据转换为Qt模型的数据。 ```c++ int PersonModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return persons.count(); } int PersonModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 3; } QVariant PersonModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() >= persons.size() || index.row() < 0) return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole) { const auto &person = persons.at(index.row()); if (index.column() == 0) return person.name; else if (index.column() == 1) return person.age; else if (index.column() == 2) return person.gender; } return QVariant(); } QVariant PersonModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) return QVariant(); if (orientation == Qt::Horizontal) { switch (section) { case 0: return tr("Name"); case 1: return tr("Age"); case 2: return tr("Gender"); default: return QVariant(); } } return QVariant(); } ``` 在上面的代码中,我们重写了rowCount、columnCount、data和headerData方法,并将Person结构体的数据转换为Qt模型的数据。 4. 使用TableView显示自定义数据结构 最后,你可以使用TableView来显示自定义数据结构。在MainWindow类中,你可以创建一个TableView,并将它设置为PersonModel的视图。 ```c++ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // create person model PersonModel *personModel = new PersonModel(this); personModel->persons.append({ "Tom", 25, "Male" }); personModel->persons.append({ "Alice", 30, "Female" }); personModel->persons.append({ "John", 40, "Male" }); // create table view QTableView *tableView = new QTableView(this); tableView->setModel(personModel); // set table view properties tableView->setSelectionMode(QAbstractItemView::SingleSelection); tableView->setSelectionBehavior(QAbstractItemView::SelectRows); tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // set central widget setCentralWidget(tableView); } ``` 在上面的代码中,我们创建了一个PersonModel,并将它设置为TableView的模型。然后,我们设置了TableView的一些属性,并将它设置为MainWindow的中央窗口部件。 这样,你就可以使用TableView来显示自定义数据结构了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值