Duilib 虚表

源码下载地址:https://gitee.com/Ailsc/Duilib

在duilib的实际应用过程中我们可能会遇见很大的数据量需要展示。此时如果我们使用传统的列表展示将会有如下问题:


 1. ListItem 占用大量内存
 2. 重绘将会产生大量的cpu消耗和卡顿
 3. 排序和滚动导致卡死

所以此时我们就要使用一种新的技术支持:虚表。

思想分析主要分为两部分(10W数据为例):展示+滚动条
 1. 由于展示空间的限制,所以我们最多可以展示数据量 max_item = 窗口高度/Item高度 + 1)
 2. 因为数据量远远大于max_item,所以需要滚动条。滚动条范围:hrange = (10w/Item高度 - max_item)
 3. 绘制,由于duilib样式的多样性,所以需要定制Item的样式和当前展示数据内容

实现接口:

//是否启用续表
void SetVirtual(bool bUse = false);
//设置续表的样式
void SetVirtualItemFormat(PULVirtualItemFormat vrtualitemfroamt);
//设置续表的数据量
void SetVirtualItemCount(int nCountItem)
//绘画续表的样式,当Item内容发生变更的时候发送消息,绘制数据内容
DUI_MSGTYPE_DRAWITEM:
wparam = 当前行数据控件 (CControlUI*)msg.wParam
lParam = 当前行数

具体实现代码:

//开启续表
virtual void InitWindow()
{
	__super::InitWindow();
	m_plist = static_cast<CListUI*>(m_PaintManager.FindControl(_T("list")));
	///> 设置数据行为格式
	m_plist->SetVirtual(true);
	m_plist->SetVirtualItemFormat(CreateVirtualItem);
	TCHAR szBuf[10] = _T("");
	for (int i = 1;i <= ITEMCOUNT;++i)
	{
		sprintf_s(szBuf,_T("%06d"),i);
		m_vdata.push_back(szBuf);
	}
	m_plist->SetVirtualItemCount(ITEMCOUNT);
}

//处理绘制消息
virtual void Notify(TNotifyUI& msg)
{
	if(msg.sType == DUI_MSGTYPE_DRAWITEM)
	{
		DrawItem((CControlUI*)msg.wParam,msg.lParam);
	}
	__super::Notify(msg);
}

//根据行内容绘画续表
void DrawItem(CControlUI *pControl,int nRow)
{
	CDuiString strFormat;
	CListHBoxElementUI *pHBox = static_cast<CListHBoxElementUI*>(pControl-GetInterface(DUI_CTR_LISTHBOXELEMENT));
	if(pHBox && nRow < ITEMCOUNT)
	{
		strFormat.Format(_T("%d"),nRow+1);
		pHBox->GetItemAt(0)->SetText(strFormat);
		pHBox->GetItemAt(1)->SetText(m_vdata[nRow]);
	}
}

//指定虚表样式
CControlUI* CreateVirtualItem()
{
	CListHBoxElementUI *pHBox = new CListHBoxElementUI;
	//> 设置行高
	pHBox->SetFixedHeight(28);
	///> 位置
	CCheckBoxUI *pCheckBox = new CCheckBoxUI;
	pCheckBox->SetAttributeList(_T("selectedimage=\"file='skin\\res\\checked.png' dest='0,2,16,18'\" normalimage=\"file='skin\\res\\unchecked.png' dest='0,2,16,18'\""));
	pCheckBox->SetFixedHeight(16);
	pCheckBox->SetFixedWidth(30);

	//> 名称
	CLabelUI *pLabel = new CLabelUI;

	///> 操作区域
	CHorizontalLayoutUI *pHorizon = new CHorizontalLayoutUI;
	CButtonUI *pButton = new CButtonUI;
	pButton->SetAttributeList(_T("normalimage=\"file='skin\\res\\btn_normal.png'\" hotimage=\"file='skin\\res\\btn_hot.png'\" pushedimage=\"file='skin\\res\\btn_pushed.png'\""));
	pButton->SetFixedHeight(16);
	pButton->SetFixedWidth(30);
	pButton->SetText(_T("编辑"));
	CHorizontalLayoutUI *pAxis = new CHorizontalLayoutUI;
	pAxis->SetFixedWidth(20);

	CButtonUI *pButton2 = new CButtonUI;
	pButton2->SetAttributeList(_T("normalimage=\"file='skin\\res\\btn_normal.png'\" hotimage=\"file='skin\\res\\btn_hot.png'\" pushedimage=\"file='skin\\res\\btn_pushed.png'\""));
	pButton2->SetFixedHeight(16);
	pButton2->SetFixedWidth(30);
	pButton2->SetText(_T("删除"));

	pHorizon->Add(pButton);
	pHorizon->Add(pAxis);
	pHorizon->Add(pButton2);

	pHBox->Add(pCheckBox);
	pHBox->Add(pLabel);
	pHBox->Add(pHorizon);

	return pHBox;
}

最终效果:
在这里插入图片描述

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值