666666666666

as.net/asfa/1.html

as.net/asfa/2.html

as.net/asfa/3.html

as.net/asfa/4.html
as.net/asfa/5.html
personModel::personModel(QObject *parent, QSqlDatabase db) : baseModel(parent, db) { } int personModel::rowCount(const QModelIndex &parent) const { int totalCount = Database::GetInstance()->getPersonCount(m_filter); return qMin(m_pageSize, totalCount - (m_currentPage - 1) * m_pageSize); } int personModel::columnCount(const QModelIndex &parent) const { return 7; } QVariant personModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (index.column() == 5) { if (role == Qt::EditRole || role == Qt::DecorationRole || role == Qt::DisplayRole) { QByteArray imageData = QSqlTableModel::data(index, Qt::EditRole).toByteArray(); if (role == Qt::EditRole || role == Qt::DisplayRole) { // 直接返回原始字节数据 return imageData; } if (!imageData.isEmpty()) { QPixmap pixmap; if (pixmap.loadFromData(imageData)) { return pixmap.scaled(95, 95, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); } } } return QVariant(); } //编辑和显示模式确保模型可以拿到数据 if (role == Qt::DisplayRole || role == Qt::EditRole) { return QSqlTableModel::data(index, role); } return QVariant(); } QVariant personModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { switch (section) { case 0: return "序号"; case 1: return "工号"; case 2: return "姓名"; case 3: return "性别"; case 4: return "部门"; case 5: return "照片"; case 6: return "操作"; default: return QVariant(); } } return QVariant(); } void personModel::setPage(int page) { if (page != m_currentPage) { beginResetModel(); m_currentPage = page; m_filter = "limit" + endResetModel(); } }void PersonManagement::initUI() { setObjectName("PersonManagement"); m_personModel = new personModel(this, Database::GetInstance()->getDB()); m_personModel->setTable("personInfo"); m_personModel->select(); // 创建数据模型 m_personTable = new QTableView(this); m_personTable->setModel(m_personModel); QHeaderView* horizontalHeader = m_personTable->horizontalHeader(); // 设置除第五列外的所有列自由拉伸 for (int i = 0; i < m_personModel->columnCount(); ++i) { if (i != 5 || i != 6) { horizontalHeader->setSectionResizeMode(i, QHeaderView::Stretch); } } // 设置第五列固定宽度 horizontalHeader->setSectionResizeMode(5, QHeaderView::Fixed); m_personTable->setColumnWidth(5, 100); // 设置第六列固定宽度 horizontalHeader->setSectionResizeMode(6, QHeaderView::Fixed); m_personTable->setColumnWidth(6, 130); // 其他设置保持不变 m_personTable->verticalHeader()->setVisible(false); m_personTable->setEditTriggers(QAbstractItemView::NoEditTriggers); m_personTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_personTable->hideColumn(0); m_personTable->verticalHeader()->setDefaultSectionSize(100); // 创建搜索框 m_searchLineEdit = new QLineEdit(this); m_searchLineEdit->setPlaceholderText("输入姓名搜索人员..."); m_searchLineEdit->setMinimumWidth(250); // 使用 Qt 自带的搜索图标(兼容性版本) QIcon searchIcon = style()->standardIcon(QStyle::SP_FileDialogContentsView); QAction *searchAction = new QAction(searchIcon, "搜索", this); m_searchLineEdit->addAction(searchAction, QLineEdit::TrailingPosition); // 创建按钮 m_addPersonButton = new QPushButton("增加人员", this); m_addPersonButton->setFixedSize(95, 30); m_exportButton = new QPushButton("导出数据", this); m_exportButton->setFixedSize(95, 30); m_importButton = new QPushButton("导入数据", this); m_importButton->setFixedSize(95, 30); QPushButton *rename = new QPushButton("修改照片名", this); connect(rename, &QPushButton::clicked, this, &PersonManagement::onrename); // 按钮布局(添加间距和对齐) QHBoxLayout *buttonLayout = new QHBoxLayout(); buttonLayout->addWidget(m_searchLineEdit); // 搜索框居左 buttonLayout->addStretch(1); // 间距 buttonLayout->addWidget(m_addPersonButton); buttonLayout->addSpacing(10); // 按钮间距 buttonLayout->addWidget(m_exportButton); buttonLayout->addSpacing(10); buttonLayout->addWidget(m_importButton); buttonLayout->addWidget(rename); buttonLayout->setContentsMargins(10, 10, 10, 10); // 布局边距 //分页 m_upPageBtn = new QPushButton("上一页", this); m_upPageBtn->setFixedSize(80, 30); m_downPageBtn = new QPushButton("下一页", this); m_downPageBtn->setFixedSize(80, 30); m_jumpBtn = new QPushButton("跳转", this); m_jumpBtn->setFixedSize(80, 30); m_currentPage = new QLabel("当前 页", this); m_currentPage->setFixedSize(80, 30); //跳转输入页 m_jumpBox = new QSpinBox(this); m_jumpBox->setRange(1,999); m_jumpBox->setFixedSize(50, 30); QHBoxLayout *pageTurnLayout = new QHBoxLayout(); pageTurnLayout->addWidget(m_upPageBtn); pageTurnLayout->addSpacing(35); pageTurnLayout->addWidget(m_currentPage); pageTurnLayout->addSpacing(35); pageTurnLayout->addWidget(m_downPageBtn); QHBoxLayout *pageJumpLayout = new QHBoxLayout(); pageJumpLayout->addWidget(m_jumpBox); pageJumpLayout->addSpacing(10); pageJumpLayout->addWidget(m_jumpBtn); pageJumpLayout->setContentsMargins(5, 5, 5, 5); // 布局边距 QHBoxLayout *pageLayout = new QHBoxLayout(); pageLayout->addLayout(pageTurnLayout); pageLayout->addLayout(pageJumpLayout); // 主布局 QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addLayout(buttonLayout); mainLayout->addWidget(m_personTable); mainLayout->addLayout(pageLayout); mainLayout->setContentsMargins(10, 10, 10, 10); mainLayout->setSpacing(10); qDebug() << " 1111111111 "; // 设置操作委托到操作列 EditDeleteButtonDelegate *delegate = new EditDeleteButtonDelegate(this); m_personTable->setItemDelegateForColumn(6, delegate); m_totalRows = Database::GetInstance()->getPersonCount(); m_totalPages = (m_totalRows + m_pageSize - 1) / m_pageSize; if (m_totalPages == 0) m_totalPages = 1; // 没有数据时显示第1页 m_jumpBox->setRange(1, m_totalPages); qDebug() << " 000000000 " << m_totalRows << m_totalPages; updatePage(); connect(delegate, &EditDeleteButtonDelegate::editClicked, this, [this](const QModelIndex &index) { onEditButtonClicked(index); }); connect(delegate, &EditDeleteButtonDelegate::deleteClicked, this, [this](const QModelIndex &index) { onDelButtonClicked(index); }); // 连接信号 connect(m_addPersonButton, &QPushButton::clicked, this, &PersonManagement::onAddPersonClicked); connect(m_exportButton, &QPushButton::clicked, this, &PersonManagement::onExportClicked); connect(m_importButton, &QPushButton::clicked, this, &PersonManagement::onImportClicked); connect(searchAction, &QAction::triggered, this, &PersonManagement::onSearchClicked); connect(m_searchLineEdit, &QLineEdit::returnPressed, this, &PersonManagement::onSearchClicked); connect(m_upPageBtn, &QPushButton::clicked, this, &PersonManagement::onPrevPage); connect(m_downPageBtn, &QPushButton::clicked, this, &PersonManagement::onNextPage); connect(m_jumpBtn, &QPushButton::clicked, this, &PersonManagement::onJumpPage); } int Database::getPersonCount(const QString &filter) { if (!db.isOpen()) { if (!openDatabase()) { return 0; } } QReadLocker locker(&m_rwLock); QSqlQuery query(db); QString queryStr = "SELECT COUNT(*) FROM personInfo"; if (!filter.isEmpty()) { queryStr += " WHERE " + filter; } if (query.exec(queryStr)) { if (query.next()) { return query.value(0).toInt(); } } else { qDebug() << query.lastError().text(); } qDebug() <<"666666666666"; return 0; } 基于上面的代码实现分页,我的数据比较多,分页这边要使用数据库查询进行限制,每页20行数据
07-01
<think>我们参考引用内容,特别是引用[1]和引用[2]中提到的分页实现方法。在QSqlTableModel中,我们可以通过设置查询的起始位置和每页数量来实现分页。但是注意,QSqlTableModel本身并没有直接提供分页功能,我们需要通过设置SQL语句的LIMIT和OFFSET子句来实现。然而,QSqlTableModel的setFilter()方法可以设置WHERE条件,但无法直接设置LIMIT和OFFSET。因此,我们可以考虑以下两种方法:方法1:使用QSqlTableModel的setQuery()方法,但注意QSqlTableModel通常用于单表操作,且其内部查询是自动生成的。我们可以通过子类化QSqlTableModel,重写selectStatement()方法来自定义生成的SQL语句,加入LIMIT和OFFSET。方法2:使用QSqlQuery执行分页查询,然后将结果设置到QStandardItemModel中,但这样会失去QSqlTableModel的自动数据库同步功能。这里我们采用方法1,因为我们需要保持模型与数据库的同步能力(如编辑后自动提交)。步骤:1.子类化QSqlTableModel,重写selectStatement()函数,在生成的SELECT语句后添加LIMIT和OFFSET子句。2.在子类中添加设置当前页和每页行数的方法。3.当翻页时,重新执行select()以获取新页的数据。注意:由于不同数据库的语法可能不同(如MySQL使用LIMIT,而PostgreSQL使用LIMITOFFSET),这里假设使用MySQL。下面是一个示例实现:首先,创建子类PagedTableModel:```cppclassPagedTableModel: publicQSqlTableModel{Q_OBJECTpublic:PagedTableModel(QObject*parent= nullptr, QSqlDatabasedb =QSqlDatabase());voidsetPage(int pageNumber, introwsPerPage);//设置当前页和每页行数inttotalRowCount();//获取总行数(用于计算总页数)protected:QStringselectStatement() constoverride;private:intm_pageNumber=1;intm_rowsPerPage=20;};PagedTableModel::PagedTableModel(QObject*parent, QSqlDatabasedb):QSqlTableModel(parent,db){ }voidPagedTableModel::setPage(intpageNumber, introwsPerPage){m_pageNumber =pageNumber;m_rowsPerPage= rowsPerPage;//重新执行查询select(); }intPagedTableModel::totalRowCount() {//执行一次不带分页的查询,获取总行数QString queryStr= QString("SELECTCOUNT(*)FROM %1").arg(tableName());QSqlQueryquery(database());if(query.exec(queryStr)&& query.next()){return query.value(0).toInt();}return -1;} QString PagedTableModel::selectStatement() const{//首先获取基类的查询语句(不带分页)QStringbaseQuery= QSqlTableModel::selectStatement();//如果是MySQL,添加LIMIT和OFFSET//注意:基类的语句可能包含WHERE、ORDER BY等,所以我们在最后添加//计算偏移量int offset= (m_pageNumber -1) *m_rowsPerPage;QString pagedQuery= baseQuery +QString("LIMIT%1OFFSET %2").arg(m_rowsPerPage).arg(offset);returnpagedQuery;} ```注意:以上代码中,我们假设基类的selectStatement()返回的语句不包含LIMIT。另外,总行数的计算可能需要根据过滤条件进行,所以上面的totalRowCount()没有考虑过滤条件。如果需要考虑,可以修改为:```cppint PagedTableModel::totalRowCount(){//如果有过滤条件,需要加上QString whereClause= filter();QString queryStr =QString("SELECT COUNT(*) FROM%1").arg(tableName());if (!whereClause.isEmpty()) {queryStr +=" WHERE" +whereClause;}QSqlQueryquery(database());if(query.exec(queryStr)&& query.next()){return query.value(0).toInt();}return -1;} ```使用示例: ```cpp//创建模型PagedTableModel *model =new PagedTableModel(this,db); model->setTable("your_table_name");model->setEditStrategy(QSqlTableModel::OnManualSubmit);//设置编辑策略//设置第一页,每页20行model->setPage(1,20);model->select();//将模型设置到视图中ui->tableView->setModel(model);//翻页时,调用setPage设置新的页码,然后调用select()(在setPage中已经调用了) ```注意:在翻页操作中,我们只需要调用setPage()即可重新加载数据。另外,引用[2]中提到了一个curPage索引,并调用select(),这与我们的做法类似。但是,上述实现存在一个问题:当有排序时,基类的selectStatement()会包含ORDERBY子句,而我们在后面添加LIMIT和OFFSET是合法的。但是,如果基类的查询语句已经包含LIMIT(比如在子查询中),则可能出错。不过QSqlTableModel默认生成的语句是不包含LIMIT的,所以通常安全。另外,我们还可以在子类中提供当前页和每页行数的访问函数,以及总页数计算函数。这种方法实现了分页查询,并且保持了QSqlTableModel的特性(如编辑、提交等)。相关问题:1.如何在使用分页的同时支持排序?2.如何实现上一页、下一页的按钮功能?3.如何显示总页数和当前页码?4.在分页情况下,如何确保新增或删除数据后分页信息正确更新?</think>### Qt QSqlTableModel 分页实现(每页20条数据) #### 实现原理 通过`QSqlTableModel`结合SQL的`LIMIT`和`OFFSET`子句实现分页功能: - `LIMIT`:限制每页行数(20条) - `OFFSET`:设置数据偏移量(`(当前页-1)*20`) - 公式:$$ \text{offset} = (\text{currentPage} - 1) \times \text{pageSize} $$ #### 完整实现步骤 1. **数据库连接** ```cpp QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("localhost"); db.setDatabaseName("test_db"); db.setUserName("root"); db.setPassword("123456"); if (!db.open()) { qDebug() << "Database error:" << db.lastError(); } ``` 2. **分页模型类(核心)** ```cpp class PagedTableModel : public QSqlTableModel { public: PagedTableModel(QObject *parent = nullptr) : QSqlTableModel(parent), currentPage(1), pageSize(20) {} void setPage(int page) { currentPage = qMax(1, page); updateQuery(); } int totalPages() { QSqlQuery query(QString("SELECT COUNT(*) FROM %1").arg(tableName())); query.exec(); query.next(); int total = query.value(0).toInt(); return qCeil(static_cast<qreal>(total) / pageSize); } protected: QString selectStatement() const override { // 核心分页SQL生成 int offset = (currentPage - 1) * pageSize; return QString("SELECT * FROM %1 LIMIT %2 OFFSET %3") .arg(tableName()) .arg(pageSize) .arg(offset); } private: void updateQuery() { // 强制刷新查询 setQuery(selectStatement()); select(); } int currentPage; int pageSize; }; ``` 3. **初始化与使用** ```cpp // 初始化模型 PagedTableModel *model = new PagedTableModel(this); model->setTable("employees"); model->select(); // 加载第一页数据 // 关联到QTableView ui->tableView->setModel(model); ``` 4. **翻页控制** ```cpp // 下一页按钮点击 void MainWindow::on_nextButton_clicked() { int total = model->totalPages(); int nextPage = qMin(model->currentPage + 1, total); model->setPage(nextPage); updatePageLabel(); // 更新页码显示 } // 上一页按钮点击 void MainWindow::on_prevButton_clicked() { int prevPage = qMax(1, model->currentPage - 1); model->setPage(prevPage); updatePageLabel(); } ``` 5. **页码显示更新** ```cpp void MainWindow::updatePageLabel() { ui->pageLabel->setText( QString("Page %1/%2") .arg(model->currentPage) .arg(model->totalPages()) ); } ``` #### 关键说明 1. **重写`selectStatement()`** 通过重写此方法注入`LIMIT`和`OFFSET`子句,实现分页查询[^1][^2]。 2. **性能优化** - 使用`COUNT(*)`获取总行数计算总页数 - 避免一次性加载全部数据 - 数据库端完成分页处理 3. **数据同步** 设置编辑策略保证数据实时同步: ```cpp model->setEditStrategy(QSqlTableModel::OnFieldChange); ``` 4. **注意事项** - 排序时需在基类查询中包含`ORDER BY`子句 - 过滤条件使用`setFilter()`自动注入 - 不同数据库分页语法可能不同(MySQL/Oracle/PostgreSQL) #### 界面效果 ``` [ 上一页 ] Page 3/12 [ 下一页 ] +----+------------+-----------+ | ID | Name | Department| +----+------------+-----------+ | 41 | John Doe | Engineering| | 42 | Jane Smith | Marketing | | ...(共20行)... +----+------------+-----------+ ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值