QT中QTableWidget加载大量数据不卡顿的解决

 更新时间:2023年07月17日 09:27:52   作者:Sweet hort  
本文主要介绍了QT中QTableWidget加载大量数据不卡顿的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

最近在模仿网易云音乐的UI,积累自己的代码能力,在使用QTabbleWidget的时候发现加载大量数据会导致卡顿,这个不能忍。

原因

设置了自适应宽度

// item 水平表头自适应大小
	tab->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
	// item 垂直表头自适应大小
	ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
 	//试着设置为:  QHeaderView::Fixed 看看是否还会卡顿

加载的数据太大

解决方案

  • QTableView 配合 Model (推荐)
  • 我们知道 QTableWidget 每次显示的数据有限(屏幕只有这么大),我们利用这一点来实现动态加载item,解决卡顿的问题
  • 使用事件过滤器,或者 重写鼠标事件,
//需要重写的虚函数
	virtual void wheelEvent(QWheelEvent* event)
	//事件过滤器
	virtual bool eventFilter(QObject* obj, QEvent* event)

举例说明

1.我们首先先加载一定量的数据,这样就不会卡了。

2.为了防止越界,每次循环我们都应该判断一下

3.用一个 curtableindex 来记录当前数据的位置,方便之后加载剩余的数据

void SongMenu::loadData()
{
	int len = taglsit.length();
	for (int i = 0; i != 20; ++i) {
		if (i >= len)return;
		ui->tab_SongTable->insertRow(i);
		//添加窗口小部件
		ui->tab_SongTable->setCellWidget(i, 0, base->setItemWidget(1));
		QTableWidgetItem* item1 = new QTableWidgetItem(taglsit.at(i).Title);
		QTableWidgetItem* item2 = new QTableWidgetItem(taglsit.at(i).Artist);
		QTableWidgetItem* item3 = new QTableWidgetItem(taglsit.at(i).Ablue);
		QTableWidgetItem* item4 = new QTableWidgetItem(taglsit.at(i).Duration);
		ui->tab_SongTable->setItem(i, 1, item1);
		ui->tab_SongTable->setItem(i, 2, item2);
		ui->tab_SongTable->setItem(i, 3, item3);
		ui->tab_SongTable->setItem(i, 4, item4);
	}
	curtableindex = 20;
	//下面例子是加载大量数据会卡顿,原因:一次性把所有的数据都添加了且设置了自适应宽度
	/*foreach(const Temptag & rhs, taglsit) {
		ui->tab_SongTable->insertRow(index);
		ui->tab_SongTable->setCellWidget(index, 0, base->setItemWidget(1));
		QTableWidgetItem* item1 = new QTableWidgetItem(rhs.Artist);
		QTableWidgetItem* item2 = new QTableWidgetItem(rhs.Title);
		QTableWidgetItem* item3 = new QTableWidgetItem(rhs.Ablue);
		QTableWidgetItem* item4 = new QTableWidgetItem(rhs.Duration);
		ui->tab_SongTable->setItem(index, 1, item1);
		ui->tab_SongTable->setItem(index, 2, item2);
		ui->tab_SongTable->setItem(index, 3, item3);
		ui->tab_SongTable->setItem(index, 4, item4);
	}*/
}

插入以后的效果图

这里并没有加载全部的数据。

重新鼠标事件

函数原型:

virtual void wheelEvent(QWheelEvent* event)

wheelEvent() 实现方法

void Base::wheelEvent(QWheelEvent* event)
{
	//滑动一次 y() == 120
	//y() > 0 鼠标滚轮向前滑动, y() < 0 鼠标滚轮向自己滑动
	if (event->angleDelta().y() < 0) {
		emit loadNextPage();
	}
}

事件过滤器

函数原型:

virtual bool eventFilter(QObject* obj, QEvent* event)

eventFilter() 实现方法

bool Base::eventFilter(QObject* obj, QEvent* event)
{
	if (obj == tab) {
		if (event->type() == QEvent::Wheel) {
			QWheelEvent* wheel = static_cast<QWheelEvent*>(event);
			//y() < 0 鼠标滚轮向自己滑动 
			if (wheel->angleDelta().y() < 0) {
				//发射信号,然后处理数据
				emit loadNextPage(); 
			}
		}
	}
	return QTableWidget::eventFilter(obj,event);
}
//然后在 构造函数中安装事件过滤器
ui->tab_SongTable->installEventFilter(this);

实现滑动加载

前面已经实现了事件过滤器,和重写鼠标事件,接下来就是加载数据了,方法很简单,只要连接信号,然后加载数据就行了

//加载剩余的数据
	connect(base, &Base::loadNextPage, this, [&]() {
	//每次滚动到底部都加载5条数据,和前面一样,检查边界,以防越界
		for (int i = 0; i != 5; i++) {
			if (curtableindex >= taglsit.length()) {
				return;
			}
			else
			{
				//拿到ui->tab_SongTable尾部的索引,之后往尾部添加数据
				int currow = ui->tab_SongTable->rowCount();
				ui->tab_SongTable->insertRow(currow);
				ui->tab_SongTable->setCellWidget(currow, 0, base->setItemWidget(1));
				QTableWidgetItem* item1 = new QTableWidgetItem(taglsit.at(currow).Title);
				QTableWidgetItem* item2 = new QTableWidgetItem(taglsit.at(currow).Artist);
				QTableWidgetItem* item3 = new QTableWidgetItem(taglsit.at(currow).Ablue);
				QTableWidgetItem* item4 = new QTableWidgetItem(taglsit.at(currow).Duration);
				ui->tab_SongTable->setItem(currow, 1, item1);
				ui->tab_SongTable->setItem(currow, 2, item2);
				ui->tab_SongTable->setItem(currow, 3, item3);
				ui->tab_SongTable->setItem(currow, 4, item4);
			}
			//累加索引,防止越界
			++curtableindex ;
		}
		});

总结:

到此这篇关于QT中QTableWidget加载大量数据不卡顿的解决的文章就介绍到这了,更多相关QT中QTableWidget加载卡顿内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++将模板实现放入头文件原理解析

    C++将模板实现放入头文件原理解析

    这篇文章主要为大家介绍了C++将模板实现放入头文件原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 纯C语言:递归组合数源码分享

    纯C语言:递归组合数源码分享

    这篇文章主要介绍了纯C语言:递归组合数源码,有需要的朋友可以参考一下
    2014-01-01
  • C++ 数据结构之水洼的数量算法

    C++ 数据结构之水洼的数量算法

    这篇文章主要介绍了C++ 数据结构之水洼的数量算法的相关资料,需要的朋友可以参考下
    2017-06-06
  • C++简单输出钻石菱形图效果

    C++简单输出钻石菱形图效果

    这篇文章主要介绍了C++简单输出钻石菱形图效果,涉及C++简单的数组操作与图形打印技巧,需要的朋友可以参考下
    2016-05-05
  • C语言实现推箱子游戏完整代码

    C语言实现推箱子游戏完整代码

    这篇文章主要为大家详细介绍了C语言实现推箱子游戏完整代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • C++浅析类与对象基础点

    C++浅析类与对象基础点

    类和对象是两种以计算机为载体的计算机语言的合称。对象是对客观事物的抽象,类是对对象的抽象。类是一种抽象的数据类型;变量就是可以变化的量,存储在内存中—个可以拥有在某个范围内的可变存储区域
    2022-07-07
  • C++实现百度坐标(BD09)及GCJ02与WGS84之间的转换

    C++实现百度坐标(BD09)及GCJ02与WGS84之间的转换

    这篇文章主要为大家详细介绍了C++实现百度坐标(BD09)及GCJ02与WGS84之间的转换的方法,文中的示例代码讲解详细,希望对大家有所帮助
    2023-03-03
  • C++ class和struct到底有什么区别详解

    C++ class和struct到底有什么区别详解

    这篇文章主要介绍了C++ class和struct到底有什么区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 使用root权限运行自己所编译程序的解决方法

    使用root权限运行自己所编译程序的解决方法

    本篇文章介绍了,使用root权限运行自己所编译程序的解决方法。需要的朋友参考下
    2013-05-05
  • C++进一步认识类与对象

    C++进一步认识类与对象

    类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数
    2021-10-10

最新评论