关于Qt如何解决UI界面一次性加载太多数据而卡顿的问题
思路分析:
以QTableWidget电子词典为例,每次模糊查询单词时都会产生几十种,几千甚至上万种不同的结果;
例如我们输入a,对a进行模糊查询时,势必会产生很多结果。如果我们将其所有结果全部都加载到UI界面的表格,必然会造成界面的短暂卡顿,甚至操作过快,还会导致程序未响应闪退。
那么我们该如何让解决呢,很简单,不管查询啥,都控制界面最多加载几十条数据。这样就不会卡顿啦。
孬,这种方法当然可行,但是用户没办法查看剩余其他更多的结果了,所以我们需要一种既能不让程序卡顿,又能查看到所有查询结果的方法,那就是“动态加载”;
首先因为窗口大小是死的,一开始只能看到部分数据,所以我设定每次到的查询结果,只加载15条到界面上,剩下的所有结果用一容器保存下来;
然后根据用户鼠标滑轮事件,如果用户想查看下面的数据,一般都会滑轮下滑查看,我们只需监听这一鼠标事件,每当用户滑一下滚轮,我就从容器中加载接下来的5条数据,这样就可以了,废话不多说,直接上代码。
/**
* @brief Dialog::selectData 查询数据
*/
void Dialog::selectData(QString keywords){
ui->tableWidget->clearContents(); //清空释放原表所有item
deleteAllRows();
// QString keywords = ui->lineEdit->text();
QSqlQuery sq;
QString sql;
if(ui->comboBox->currentText() == "中文"){
sql = "select * from englishwords where meaning like ?";
sq.prepare(sql);
sq.addBindValue("%" +keywords);
}
else if(ui->comboBox->currentText() == "英文"){
sql = "select * from englishwords where word like ?";
sq.prepare(sql);
sq.addBindValue(keywords + "%");
}
else{
sql = "select * from englishwords where word like ? or meaning like ?";
sq.prepare(sql);
sq.addBindValue(keywords + "%");
sq.addBindValue("%" +keywords);
}
if(sq.exec()){
int row = 0;
while(sq.next()){
int currentRowCount = ui->tableWidget->rowCount();
if(currentRowCount == row)
ui->tableWidget->insertRow(currentRowCount);
if(row < 15){
ui->tableWidget->setItem(row, 0, new QTableWidgetItem(sq.value(0).toString()));
ui->tableWidget->setItem(row, 1, new QTableWidgetItem(sq.value(1).toString()));
ui->tableWidget->setItem(row++, 2, new QTableWidgetItem(sq.value(2).toString()));
}
else{//剩余结果暂存Qlist,根据鼠标滑轮事件动态加载,直接全部加载到界面会造成卡顿
MyData md;
md.word = sq.value(0).toString();
md.pron = sq.value(1).toString();
md.meaning = sq.value(2).toString();
data.append(md);
}
}
ui->tableWidget->removeRow(row);
ui->tableWidget->show();
}
else{
QMessageBox::warning(this, "提示", "查询操作失败!" + sq.lastError().text());
}
}
/**
* @brief Dialog::deleteAllRows 删除ableWidget中所有行
*/
void Dialog::deleteAllRows(){
for(int i = ui->tableWidget->rowCount() - 1; i >= 0; --i){
ui->tableWidget->removeRow(i);
}
}
/**
* @brief Dialog::loadData 加载5条数据
* @param row
*/
void Dialog::loadData(int row){
for(int i = row; i < row + 5; i++){
ui->tableWidget->insertRow(i); //先添加行,再设置item
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(data.first().word));
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(data.first().pron));
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(data.first().meaning));
data.removeAt(0);
if(data.isEmpty())
break;
}
}
/**
* @brief Dialog::wheelEvent 鼠标滑轮事件
* @param event
*/
void Dialog::wheelEvent(QWheelEvent* event){
//滑轮下滑,加载数据
if(event->delta() < 0 && !data.isEmpty())
loadData(ui->tableWidget->rowCount());
}