• 3971阅读
  • 4回复

Qt开源作品19-通用数据库翻页查询 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 2020-05-25
## 一、前言
在Qt与数据结合编程的过程中,记录一多,基本上都需要用到翻页查看记录,翻页有个好处就是可以减轻显示数据的表格的压力,不需要一次性将数据库表的记录全部显示,也基本上没有谁在一页上需要一次性显示所有记录,搜索引擎搜索出来的结果也基本上都是翻页显示的,那么问题来了,有没有一种通用的办法可以只需要传入表名和查询条件自动翻页呢,答案是肯定的,Qt对数据库操作的封装也是相当完美的,显示也是如此,为此特意封装成了一个类,直接用就行。

**主要功能:**
1. 自动按照设定的每页多少行数据分页
2. 只需要传入表名/字段集合/每页行数/翻页指示按钮/文字指示标签
3. 提供公共静态方法绑定字段数据到下拉框
4. 建议条件字段用数字类型的主键,速度极快
5. 增加线程查询符合条件的记录总数,数据量巨大时候不会卡主界面
6. 提供查询结果返回信号,包括当前页/总页数/总记录数/查询用时
7. 可设置所有列或者某一列对齐样式例如居中或者右对齐
8. 可设置增加一列,列的位置,标题,宽度
9. 可设置要查询的字段集合

## 二、代码思路
```c++
void DbPage::bindData(const QString &sql)
{
    queryModel->setQuery(sql, QSqlDatabase::database(connName));
    tableView->setModel(queryModel);

    //依次设置列标题列宽
    int columnCount = tableView->model()->columnCount();
    int nameCount = columnNames.count();
    columnCount = columnCount > nameCount ? nameCount : columnCount;

    QList<QString> columnNames = this->columnNames;
    QList<int> columnWidths = this->columnWidths;

    //根据设置添加新列,将对应新列的标题名称和宽度按照索引位置插
    if (insertColumnIndex >= 0) {
        columnCount++;
        columnNames.insert(insertColumnIndex, insertColumnName);
        columnWidths.insert(insertColumnIndex, insertColumnWidth);
        queryModel->insertColumn(insertColumnIndex);
    }

    //设置列标题和列宽度
    for (int i = 0; i < columnCount; i++) {
        queryModel->setHeaderData(i, Qt::Horizontal, columnNames.at(i));
        tableView->setColumnWidth(i, columnWidths.at(i));
    }

    if (labPageCurrent != 0) {
        labPageCurrent->setText(QString("第 %1 页").arg(pageCurrent));
    }

    if (labPageCount != 0) {
        labPageCount->setText(QString("共 %1 页").arg(pageCount));
    }

    if (labResultCount != 0) {
        labResultCount->setText(QString("共 %1 条").arg(resultCount));
    }

    if (labResultCurrent != 0) {
        labResultCurrent->setText(QString("每页 %1 条").arg(resultCurrent));
    }

    if (labInfo != 0) {
        labInfo->setText(QString("共 %1 条  每页 %2 条  共 %3 页  第 %4 页").arg(resultCount).arg(resultCurrent).arg(pageCount).arg(pageCurrent));
    }

    //发送结果信号
    emit receivePage(pageCurrent, pageCount, resultCount, resultCurrent);
}

void DbPage::slot_receiveCount(quint32 count, double msec)
{
    if (labResult != 0) {
        labResult->setText(QString("查询用时 %1 秒").arg(QString::number(msec / 1000, 'f', 3)));
    }

    resultCount = count;

    int yushu = resultCount % resultCurrent;

    //不存在余数,说明是整行,例如300%5==0
    if (yushu == 0) {
        if (resultCount > 0 && resultCount < resultCurrent) {
            pageCount = 1;
        } else {
            pageCount = resultCount / resultCurrent;
        }
    } else {
        pageCount = (resultCount / resultCurrent) + 1;
    }

    //2014-10-9增加翻页按钮可用不可用处理,如果只有一页数据,则翻页按钮不可用
    if (pageCount <= 1) {
        btnFirst->setEnabled(false);
        btnLast->setEnabled(false);
        btnNext->setEnabled(false);
        btnPre->setEnabled(false);
    } else {
        btnFirst->setEnabled(true);
        btnLast->setEnabled(true);
        btnNext->setEnabled(true);
        btnPre->setEnabled(true);
    }

    tempSql = QString("select %1 from %2 %3 order by %4").arg(selectColumn).arg(tableName).arg(whereSql).arg(orderSql);
    sql = QString("%1 limit %2,%3;").arg(tempSql).arg(startIndex).arg(resultCurrent); //组织分页SQL语句

    bindData(sql);
}

void DbPage::first()
{
    if (pageCount > 1) {
        startIndex = 0;
        pageCurrent = 1;
        sql = QString("%1 limit %2,%3;").arg(tempSql).arg(startIndex).arg(resultCurrent);
        bindData(sql);
        btnLast->setEnabled(true);
        btnNext->setEnabled(true);
    }

    btnFirst->setEnabled(false);
    btnPre->setEnabled(false);
}

void DbPage::previous()
{
    if (pageCurrent > 1) {
        pageCurrent--;
        startIndex -= resultCurrent;
        sql = QString("%1 limit %2,%3;").arg(tempSql).arg(startIndex).arg(resultCurrent);
        bindData(sql);
        btnLast->setEnabled(true);
        btnNext->setEnabled(true);
    }

    if (pageCurrent == 1) {
        btnFirst->setEnabled(false);
        btnPre->setEnabled(false);
    }
}

void DbPage::next()
{
    if (pageCurrent < pageCount) {
        pageCurrent++;
        startIndex += resultCurrent;
        sql = QString("%1 limit %2,%3;").arg(tempSql).arg(startIndex).arg(resultCurrent);
        bindData(sql);
        btnFirst->setEnabled(true);
        btnPre->setEnabled(true);
    }

    if (pageCurrent == pageCount) {
        btnLast->setEnabled(false);
        btnNext->setEnabled(false);
    }
}

void DbPage::last()
{
    if (pageCount > 0) {
        startIndex = (pageCount - 1) * resultCurrent;
        pageCurrent = pageCount;
        sql = QString("%1 limit %2,%3;").arg(tempSql).arg(startIndex).arg(resultCurrent);
        bindData(sql);
        btnFirst->setEnabled(true);
        btnPre->setEnabled(true);
    }

    btnLast->setEnabled(false);
    btnNext->setEnabled(false);
}
```

## 三、效果图



## 四、开源主页
**以上作品完整源码下载都在开源主页,会持续不断更新作品数量和质量,欢迎各位关注。**

1. 国内站点:[https://gitee.com/feiyangqingyun/QWidgetDemo](https://gitee.com/feiyangqingyun/QWidgetDemo)
2. 国际站点:[https://github.com/feiyangqingyun/QWidgetDemo](https://github.com/feiyangqingyun/QWidgetDemo)
3. 个人主页:[https://blog.csdn.net/feiyangqingyun](https://blog.csdn.net/feiyangqingyun)
4. 知乎主页:[https://www.zhihu.com/people/feiyangqingyun/](https://www.zhihu.com/people/feiyangqingyun/)
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线九重水

只看该作者 1楼 发表于: 2020-05-25
你是不是想做培训?

只看该作者 2楼 发表于: 2020-06-19
武哥,问您一个问题。就像这种,QTableView显示的一栏,如果超范围了,应该如何设置,让它能够自动换行,而整个表也能跟着自动换行?

例如您图片,第一行“日志类型”中第一行,“用户操作”,如果里面填写“用户操作用户操作”,那么表格自动适应换行?
离线miaxislink

只看该作者 3楼 发表于: 2020-07-12
看看前辈们的作品,学习依一下
离线飞翔梦幻

只看该作者 4楼 发表于: 2021-02-04
回 九重水 的帖子
九重水:你是不是想做培训?[表情]  (2020-05-25 09:02) 

整天发一些 没有源码开源的东西,估计是想开培训班
快速回复
限100 字节
 
上一个 下一个